@ikas/code-components-mcp 1.4.0-beta.18 → 1.4.0-beta.181
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/data/framework.json +133 -29
- package/data/migration.json +10 -4
- package/data/section-templates/account-info-section/children/AccountFavorites/ikas-config-snippet.json +13 -0
- package/data/section-templates/account-info-section/children/AccountOrders/index.tsx +1 -1
- package/data/section-templates/account-info-section/ikas-config-snippet.json +19 -0
- package/data/section-templates/add-to-cart/ikas-config-snippet.json +17 -0
- package/data/section-templates/add-to-cart/index.tsx +16 -2
- package/data/section-templates/add-to-cart/sub-components/QuantitySelector/index.tsx +11 -3
- package/data/section-templates/add-to-cart/utils/cartLimits.ts +24 -0
- package/data/section-templates/blog-home-section/ikas-config-snippet.json +2 -0
- package/data/section-templates/blog-home-section/index.tsx +2 -1
- package/data/section-templates/blog-post-section/ikas-config-snippet.json +2 -0
- package/data/section-templates/blog-post-section/index.tsx +3 -2
- package/data/section-templates/bundle-products/hooks/useBundleProducts.ts +7 -6
- package/data/section-templates/bundle-products/ikas-config-snippet.json +20 -0
- package/data/section-templates/cart-section/components/EmptyState/index.tsx +1 -1
- package/data/section-templates/cart-section/sub-components/CartItem/index.tsx +66 -24
- package/data/section-templates/cart-section/sub-components/CartItem/styles.css +14 -0
- package/data/section-templates/cart-section/sub-components/QuantitySelector/index.tsx +11 -3
- package/data/section-templates/cart-section/utils/cartLimits.ts +24 -0
- package/data/section-templates/cart-section/utils/cartLineLimits.ts +100 -0
- package/data/section-templates/category-images-section/children/CategoryImageItem/ikas-config-snippet.json +4 -0
- package/data/section-templates/category-images-section/ikas-config-snippet.json +15 -0
- package/data/section-templates/category-list-section/children/CardProductName/ikas-config-snippet.json +2 -1
- package/data/section-templates/category-list-section/ikas-config-snippet.json +21 -0
- package/data/section-templates/category-list-section/index.tsx +2 -1
- package/data/section-templates/component-renderer/additional/ProductDetail/index.tsx +5 -1
- package/data/section-templates/component-renderer/ikas-config-snippet.json +13 -0
- package/data/section-templates/favorites/ikas-config-snippet.json +18 -1
- package/data/section-templates/features-section/ikas-config-snippet.json +13 -0
- package/data/section-templates/footer-section/ikas-config-snippet.json +15 -0
- package/data/section-templates/forgot-password-section/components/ForgotPasswordForm/index.tsx +1 -1
- package/data/section-templates/header-section/children/Announcements/ikas-config-snippet.json +7 -0
- package/data/section-templates/header-section/children/CookieBar/ikas-config-snippet.json +3 -0
- package/data/section-templates/header-section/children/Navbar/components/CartSidebar/index.tsx +2 -1
- package/data/section-templates/header-section/children/Navbar/components/SearchModal/index.tsx +2 -1
- package/data/section-templates/header-section/children/Navbar/ikas-config-snippet.json +27 -0
- package/data/section-templates/header-section/children/Navbar/index.tsx +6 -5
- package/data/section-templates/header-section/ikas-config-snippet.json +13 -0
- package/data/section-templates/header-section/sub-components/CartItem/index.tsx +66 -24
- package/data/section-templates/header-section/sub-components/CartItem/styles.css +14 -0
- package/data/section-templates/header-section/sub-components/QuantitySelector/index.tsx +11 -3
- package/data/section-templates/header-section/utils/cartLimits.ts +24 -0
- package/data/section-templates/header-section/utils/cartLineLimits.ts +100 -0
- package/data/section-templates/hero-slider-section/children/HeroSliderItem/ikas-config-snippet.json +18 -0
- package/data/section-templates/hero-slider-section/children/HeroSliderItem/index.tsx +12 -7
- package/data/section-templates/hero-slider-section/ikas-config-snippet.json +13 -0
- package/data/section-templates/image-handling/ikas-config-snippet.json +53 -0
- package/data/section-templates/image-handling/index.tsx +5 -1
- package/data/section-templates/login-section/ikas-config-snippet.json +2 -0
- package/data/section-templates/navigation/components/CartSidebar/index.tsx +2 -1
- package/data/section-templates/navigation/components/SearchModal/index.tsx +2 -1
- package/data/section-templates/navigation/ikas-config-snippet.json +27 -0
- package/data/section-templates/navigation/index.tsx +6 -5
- package/data/section-templates/navigation/sub-components/CartItem/index.tsx +66 -24
- package/data/section-templates/navigation/sub-components/CartItem/styles.css +14 -0
- package/data/section-templates/navigation/sub-components/QuantitySelector/index.tsx +11 -3
- package/data/section-templates/navigation/utils/cartLimits.ts +24 -0
- package/data/section-templates/navigation/utils/cartLineLimits.ts +100 -0
- package/data/section-templates/product-detail-section/children/ProductDetailAddToCart/ikas-config-snippet.json +17 -0
- package/data/section-templates/product-detail-section/children/ProductDetailAddToCart/index.tsx +16 -2
- package/data/section-templates/product-detail-section/children/ProductDetailBackInStock/components/BackInStockForm/index.tsx +92 -0
- package/data/section-templates/product-detail-section/children/ProductDetailBackInStock/ikas-config-snippet.json +175 -0
- package/data/section-templates/product-detail-section/children/ProductDetailBackInStock/index.tsx +141 -0
- package/data/section-templates/product-detail-section/children/ProductDetailBackInStock/styles.css +47 -0
- package/data/section-templates/product-detail-section/children/ProductDetailBackInStock/types.ts +25 -0
- package/data/section-templates/product-detail-section/children/ProductDetailBundleFurniture/ikas-config-snippet.json +18 -0
- package/data/section-templates/product-detail-section/children/ProductDetailBundleProduct/ikas-config-snippet.json +20 -0
- package/data/section-templates/product-detail-section/children/ProductDetailDescription/ikas-config-snippet.json +27 -0
- package/data/section-templates/product-detail-section/children/ProductDetailFeatures/ikas-config-snippet.json +29 -0
- package/data/section-templates/product-detail-section/children/ProductDetailNameFavorite/ikas-config-snippet.json +18 -1
- package/data/section-templates/product-detail-section/children/ProductDetailOffer/ikas-config-snippet.json +20 -0
- package/data/section-templates/product-detail-section/children/ProductDetailOptionSet/ikas-config-snippet.json +16 -0
- package/data/section-templates/product-detail-section/children/ProductDetailPrices/ikas-config-snippet.json +16 -0
- package/data/section-templates/product-detail-section/children/ProductDetailProductGroup/ikas-config-snippet.json +16 -0
- package/data/section-templates/product-detail-section/children/ProductDetailSku/ikas-config-snippet.json +16 -0
- package/data/section-templates/product-detail-section/children/ProductDetailVariant/ikas-config-snippet.json +17 -0
- package/data/section-templates/product-detail-section/hooks/useBundleProducts.ts +7 -6
- package/data/section-templates/product-detail-section/ikas-config-snippet.json +53 -0
- package/data/section-templates/product-detail-section/index.tsx +5 -1
- package/data/section-templates/product-detail-section/sub-components/Modal/index.tsx +120 -0
- package/data/section-templates/product-detail-section/sub-components/Modal/styles.css +70 -0
- package/data/section-templates/product-detail-section/sub-components/QuantitySelector/index.tsx +11 -3
- package/data/section-templates/product-detail-section/utils/cartLimits.ts +24 -0
- package/data/section-templates/product-pricing/ikas-config-snippet.json +16 -0
- package/data/section-templates/product-slider-section/children/CardProductName/ikas-config-snippet.json +2 -1
- package/data/section-templates/product-slider-section/ikas-config-snippet.json +17 -0
- package/data/section-templates/register-section/ikas-config-snippet.json +2 -0
- package/data/section-templates/variant-selection/ikas-config-snippet.json +17 -0
- package/data/storefront-api.json +503 -39
- package/data/storefront-types.json +9601 -6098
- package/dist/index.js +1530 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/data/storefront-api.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-
|
|
2
|
+
"generatedAt": "2026-09-01T09:14:52.779Z",
|
|
3
3
|
"functions": [
|
|
4
4
|
{
|
|
5
5
|
"name": "apiListProductBrand",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"name": "getAttributeDetailValues",
|
|
168
168
|
"displayName": "getValues",
|
|
169
169
|
"signature": "function getAttributeDetailValues(attributeDetail: IkasProductAttributeDetail): IkasProductAttributeValue[]",
|
|
170
|
-
"description": "Retrieves the attribute values for a product attribute detail, merging variant and product-level attributes.",
|
|
170
|
+
"description": "Retrieves the attribute values for a product attribute detail, merging variant and product-level attributes.\nThis is how a PRODUCT_ATTRIBUTE code-component prop is consumed: that prop hands you the\nIkasProductAttributeDetail wrapper ({ product, attributePropValue }), never the attribute value itself, so\nreading `prop.value` silently yields nothing — call this function instead.",
|
|
171
171
|
"params": [
|
|
172
172
|
{
|
|
173
173
|
"name": "attributeDetail",
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
"name": "getAttributeListValues",
|
|
196
196
|
"displayName": "getValues",
|
|
197
197
|
"signature": "function getAttributeListValues(list: IkasProductAttributeList): IkasProductAttributeMap[]",
|
|
198
|
-
"description": "Retrieves grouped attribute values for a product attribute list, combining variant and product-level attributes.",
|
|
198
|
+
"description": "Retrieves grouped attribute values for a product attribute list, combining variant and product-level attributes.\nThis is how a PRODUCT_ATTRIBUTE_LIST code-component prop is consumed: that prop hands you a single\nIkasProductAttributeList wrapper ({ product, attributeListPropValue }) — never an array — so mapping over the\nprop is a runtime error; call this function and iterate the returned { attribute, values } maps instead.",
|
|
199
199
|
"params": [
|
|
200
200
|
{
|
|
201
201
|
"name": "list",
|
|
@@ -2761,16 +2761,16 @@
|
|
|
2761
2761
|
{
|
|
2762
2762
|
"name": "getDefaultSrc",
|
|
2763
2763
|
"signature": "function getDefaultSrc(image: IkasImage): string",
|
|
2764
|
-
"description": "Returns the default source URL for an image at 1080px resolution.",
|
|
2764
|
+
"description": "Returns the default source URL for an image OR video at 1080px resolution.\n\nProduct media items (IkasProductImage) can be videos. ALWAYS check `item.isVideo`\nand render a `<video src={getDefaultSrc(item)}>` instead of an `<img>` when it is true.\nNever assume every media item is an image.",
|
|
2765
2765
|
"params": [
|
|
2766
2766
|
{
|
|
2767
2767
|
"name": "image",
|
|
2768
2768
|
"description": "- The image object to generate the default source URL for."
|
|
2769
2769
|
}
|
|
2770
2770
|
],
|
|
2771
|
-
"returns": "The CDN URL string for the image at 1080px size.",
|
|
2771
|
+
"returns": "The CDN URL string for the image or video at 1080px size.",
|
|
2772
2772
|
"returnType": "string",
|
|
2773
|
-
"example": "```typescript\nimport { getDefaultSrc } from \"@ikas/bp-storefront\";\n\
|
|
2773
|
+
"example": "```typescript\nimport { getDefaultSrc, createMediaSrcset } from \"@ikas/bp-storefront\";\n\n// Product images can be videos — ALWAYS branch on isVideo when mapping media:\n{product.images.map((item, i) =>\n item.isVideo ? (\n <video key={i} src={getDefaultSrc(item)} muted playsInline preload=\"metadata\">\n <track kind=\"captions\" />\n </video>\n ) : (\n <img key={i} src={getDefaultSrc(item)} srcSet={createMediaSrcset(item)} alt={`Product ${i + 1}`} />\n )\n)}\n```",
|
|
2774
2774
|
"categories": [
|
|
2775
2775
|
"Image"
|
|
2776
2776
|
],
|
|
@@ -2788,16 +2788,16 @@
|
|
|
2788
2788
|
{
|
|
2789
2789
|
"name": "getThumbnailSrc",
|
|
2790
2790
|
"signature": "function getThumbnailSrc(image: IkasImage): string",
|
|
2791
|
-
"description": "Returns the thumbnail source URL for an
|
|
2791
|
+
"description": "Returns the thumbnail source URL for an IMAGE at 180px resolution.\n\nVIDEOS HAVE NO 180px THUMBNAIL and no poster URL. When `image.isVideo === true` the size is\nIGNORED and this returns the same full-size .mp4 as `getDefaultSrc(image)` — so using it in a\nthumbnail-sized box (swatch, cart line, order line) downloads the whole video instead of a\n180px webp. Nothing looks broken, which makes it a silent performance regression.\n\nBranch on `item.isVideo` first and only pass images here. For the video branch in a small,\nstatic context render `<video src={getDefaultSrc(item)} preload=\"metadata\" muted playsInline>`\nwith no `autoPlay`: the browser fetches only the first frame and holds it as a stand-in poster.",
|
|
2792
2792
|
"params": [
|
|
2793
2793
|
{
|
|
2794
2794
|
"name": "image",
|
|
2795
|
-
"description": "- The image object to generate the thumbnail source URL for."
|
|
2795
|
+
"description": "- The image object to generate the thumbnail source URL for. Videos ignore the size."
|
|
2796
2796
|
}
|
|
2797
2797
|
],
|
|
2798
|
-
"returns": "The CDN URL string
|
|
2798
|
+
"returns": "The CDN URL string: a 180px image, or — for `isVideo` items — the original .mp4.",
|
|
2799
2799
|
"returnType": "string",
|
|
2800
|
-
"example": "```typescript\nimport { getThumbnailSrc } from \"@ikas/bp-storefront\";\n\
|
|
2800
|
+
"example": "```typescript\nimport { getThumbnailSrc, getDefaultSrc } from \"@ikas/bp-storefront\";\n\n// Thumbnail rail — branch on isVideo per item (no autoPlay: first frame acts as the poster):\n{product.images.map((item, i) =>\n item.isVideo ? (\n <video key={i} src={getDefaultSrc(item)} muted playsInline preload=\"metadata\">\n <track kind=\"captions\" />\n </video>\n ) : (\n <img key={i} src={getThumbnailSrc(item)} sizes=\"112px\" alt={`Thumb ${i + 1}`} />\n )\n)}\n```",
|
|
2801
2801
|
"categories": [
|
|
2802
2802
|
"Image"
|
|
2803
2803
|
],
|
|
@@ -2815,7 +2815,7 @@
|
|
|
2815
2815
|
{
|
|
2816
2816
|
"name": "getSrc",
|
|
2817
2817
|
"signature": "function getSrc(image: IkasImage, size: number): string",
|
|
2818
|
-
"description": "Generates the full CDN source URL for an image or video at the specified size, handling both legacy path-based and merchant-scoped ID formats.",
|
|
2818
|
+
"description": "Generates the full CDN source URL for an image or video at the specified size, handling both legacy path-based and merchant-scoped ID formats.\n\nNOTE: For videos (`image.isVideo === true`) the `size` argument is IGNORED — the original .mp4 is always returned.\nSo `getSrc(item, 240)` and `getDefaultSrc(item)` produce the identical URL for a video. PREFER `getDefaultSrc(item)`\nfor video `src` (no size param) — do NOT pass an arbitrary size like `getSrc(item, 240)`, it is misleading.",
|
|
2819
2819
|
"params": [
|
|
2820
2820
|
{
|
|
2821
2821
|
"name": "image",
|
|
@@ -2823,12 +2823,12 @@
|
|
|
2823
2823
|
},
|
|
2824
2824
|
{
|
|
2825
2825
|
"name": "size",
|
|
2826
|
-
"description": "- The desired image width in pixels for
|
|
2826
|
+
"description": "- The desired image width in pixels. Ignored for videos."
|
|
2827
2827
|
}
|
|
2828
2828
|
],
|
|
2829
2829
|
"returns": "The full CDN URL string for the image or video.",
|
|
2830
2830
|
"returnType": "string",
|
|
2831
|
-
"example": "```typescript\nimport { getSrc } from \"@ikas/bp-storefront\";\n\nconst src = getSrc(image, 640);\nconsole.log(src); // \"https://cdn.example.com/images/.../640/image.webp\"\n```",
|
|
2831
|
+
"example": "```typescript\nimport { getSrc, getDefaultSrc } from \"@ikas/bp-storefront\";\n\nconst src = getSrc(image, 640);\nconsole.log(src); // \"https://cdn.example.com/images/.../640/image.webp\"\n\n// For a video, use getDefaultSrc (size is ignored anyway):\n<video src={getDefaultSrc(item)} muted playsInline preload=\"metadata\" />\n```",
|
|
2832
2832
|
"categories": [
|
|
2833
2833
|
"Image"
|
|
2834
2834
|
],
|
|
@@ -2846,7 +2846,7 @@
|
|
|
2846
2846
|
{
|
|
2847
2847
|
"name": "createMediaSrcset",
|
|
2848
2848
|
"signature": "function createMediaSrcset(image?: IkasImage | null): string",
|
|
2849
|
-
"description": "Generates a complete responsive `srcset` string for an image across all standard sizes (180–3840px).",
|
|
2849
|
+
"description": "Generates a complete responsive `srcset` string for an image across all standard sizes (180–3840px).\n\nsrcset applies to `<img>` only — video media (`item.isVideo === true`) has no srcset\nand must be rendered with `<video src={getDefaultSrc(item)}>`. When mapping product\nimages, branch on `item.isVideo` first, then only use createMediaSrcset on the image branch.",
|
|
2850
2850
|
"params": [
|
|
2851
2851
|
{
|
|
2852
2852
|
"name": "image",
|
|
@@ -2855,7 +2855,7 @@
|
|
|
2855
2855
|
],
|
|
2856
2856
|
"returns": "A srcset string like `\"url 180w, url 360w, ...\"`, or an empty string if no image is provided.",
|
|
2857
2857
|
"returnType": "string",
|
|
2858
|
-
"example": "```typescript\nimport { createMediaSrcset, getDefaultSrc } from \"@ikas/bp-storefront\";\n\n<img\n
|
|
2858
|
+
"example": "```typescript\nimport { createMediaSrcset, getDefaultSrc } from \"@ikas/bp-storefront\";\n\n// Product images can be videos — ALWAYS branch on isVideo when mapping media:\n{product.images.map((item, i) =>\n item.isVideo ? (\n <video key={i} src={getDefaultSrc(item)} muted playsInline preload=\"metadata\">\n <track kind=\"captions\" />\n </video>\n ) : (\n <img\n key={i}\n src={getDefaultSrc(item)}\n srcSet={createMediaSrcset(item)}\n sizes=\"(max-width: 768px) 100vw, 50vw\"\n alt={`Product ${i + 1}`}\n />\n )\n)}\n```",
|
|
2859
2859
|
"categories": [
|
|
2860
2860
|
"Image"
|
|
2861
2861
|
],
|
|
@@ -3085,6 +3085,35 @@
|
|
|
3085
3085
|
"IkasOrderGiftPackageLine"
|
|
3086
3086
|
]
|
|
3087
3087
|
},
|
|
3088
|
+
{
|
|
3089
|
+
"name": "getIkasOrderGiftCardTotalPrice",
|
|
3090
|
+
"displayName": "getGiftCardTotalPrice",
|
|
3091
|
+
"signature": "function getIkasOrderGiftCardTotalPrice(order: IkasOrder): number",
|
|
3092
|
+
"description": "Returns the total amount covered by the gift cards (and store credits) applied to the order or cart.\n\nThis is a derived value, the API does not return it: it sums `amount` over `order.giftCardLines`.\nSubtract it from `order.totalFinalPrice` to get the amount still due.",
|
|
3093
|
+
"params": [
|
|
3094
|
+
{
|
|
3095
|
+
"name": "order",
|
|
3096
|
+
"description": "- The IkasOrder or IkasCart holding the gift card lines"
|
|
3097
|
+
}
|
|
3098
|
+
],
|
|
3099
|
+
"returns": "The summed gift card amount, or 0 when no gift card is applied",
|
|
3100
|
+
"returnType": "number",
|
|
3101
|
+
"example": "```typescript\nimport { getIkasOrderGiftCardTotalPrice } from \"@ikas/bp-storefront\";\n\nconst giftCardTotal = getIkasOrderGiftCardTotalPrice(cart);\nconst remainingPrice = cart.totalFinalPrice - giftCardTotal;\n```",
|
|
3102
|
+
"categories": [
|
|
3103
|
+
"Order",
|
|
3104
|
+
"Cart"
|
|
3105
|
+
],
|
|
3106
|
+
"related": [
|
|
3107
|
+
"removeGiftCardLine",
|
|
3108
|
+
"saveCouponCode"
|
|
3109
|
+
],
|
|
3110
|
+
"isAsync": false,
|
|
3111
|
+
"isClass": false,
|
|
3112
|
+
"parameterTypes": [
|
|
3113
|
+
"IkasOrderGiftCardTotalPrice",
|
|
3114
|
+
"IkasOrder"
|
|
3115
|
+
]
|
|
3116
|
+
},
|
|
3088
3117
|
{
|
|
3089
3118
|
"name": "getIkasOrderDistinctItemCount",
|
|
3090
3119
|
"displayName": "getDistinctItemCount",
|
|
@@ -4628,7 +4657,7 @@
|
|
|
4628
4657
|
"name": "getIkasProductAttrributeProductIds",
|
|
4629
4658
|
"displayName": "getProductIds",
|
|
4630
4659
|
"signature": "function getIkasProductAttrributeProductIds(value: IkasProductAttributeValue): string[]",
|
|
4631
|
-
"description": "Extracts and returns the product IDs from a PRODUCT-type attribute value's JSON string.",
|
|
4660
|
+
"description": "Extracts and returns the product IDs from a PRODUCT-type attribute value's JSON string.\nNOTE: the export name really is misspelled — \"Attrribute\" with a double r. It is kept as-is because\nrenaming a published export would break every theme that imports it, so import it VERBATIM; the\ncorrectly spelled `getIkasProductAttributeProductIds` does not exist and will not compile. This is\nnot a documentation typo to report or \"fix\". In the blueprint editor the display alias is\n`getProductIds`, which hides the misspelling; only direct TypeScript imports see it.",
|
|
4632
4661
|
"params": [
|
|
4633
4662
|
{
|
|
4634
4663
|
"name": "value",
|
|
@@ -7310,16 +7339,16 @@
|
|
|
7310
7339
|
"name": "getProductVariantMainImage",
|
|
7311
7340
|
"displayName": "getMainImage",
|
|
7312
7341
|
"signature": "function getProductVariantMainImage(variant: IkasProductVariant): IkasProductImage | undefined",
|
|
7313
|
-
"description": "Get the main/primary
|
|
7342
|
+
"description": "Get the main/primary media item for a product variant.\n\nThe returned IkasProductImage may be a video (`isVideo === true`) — branch on it\nand render `<video>` instead of `<img>`.",
|
|
7314
7343
|
"params": [
|
|
7315
7344
|
{
|
|
7316
7345
|
"name": "variant",
|
|
7317
7346
|
"description": "- The product variant"
|
|
7318
7347
|
}
|
|
7319
7348
|
],
|
|
7320
|
-
"returns": "The first IkasProductImage of the variant, or undefined if no images.
|
|
7349
|
+
"returns": "The first IkasProductImage of the variant, or undefined if no images. Check `.isVideo` to decide between `<video>` and `<img>`, and access `.image` to get the IkasImage for CDN helpers.",
|
|
7321
7350
|
"returnType": "IkasProductImage | undefined",
|
|
7322
|
-
"example": "```typescript\nimport { getProductVariantMainImage, getSelectedProductVariant, getDefaultSrc } from \"@ikas/bp-storefront\";\nimport { IkasProduct } from \"@ikas/bp-storefront\";\n\nfunction ProductImage({ product }: { product: IkasProduct }) {\n const variant = getSelectedProductVariant(product);\n const productImage = getProductVariantMainImage(variant);\n const image = productImage?.image;\n\n if (!image) {\n return <div className=\"no-image\">No image available</div>;\n }\n\n return <img src={getDefaultSrc(image)} alt={product.name}
|
|
7351
|
+
"example": "```typescript\nimport { getProductVariantMainImage, getSelectedProductVariant, getDefaultSrc, createMediaSrcset } from \"@ikas/bp-storefront\";\nimport { IkasProduct } from \"@ikas/bp-storefront\";\n\nfunction ProductImage({ product }: { product: IkasProduct }) {\n const variant = getSelectedProductVariant(product);\n const productImage = getProductVariantMainImage(variant);\n const image = productImage?.image;\n\n if (!image) {\n return <div className=\"no-image\">No image available</div>;\n }\n\n // Media can be a video — branch on isVideo:\n return productImage.isVideo ? (\n <video src={getDefaultSrc(image)} muted playsInline loop>\n <track kind=\"captions\" />\n </video>\n ) : (\n <img src={getDefaultSrc(image)} srcSet={createMediaSrcset(image)} alt={product.name} />\n );\n}\n```",
|
|
7323
7352
|
"categories": [
|
|
7324
7353
|
"ProductDetail",
|
|
7325
7354
|
"ProductList"
|
|
@@ -7597,14 +7626,14 @@
|
|
|
7597
7626
|
"name": "getProductVariantAppliedCampaignAmount",
|
|
7598
7627
|
"displayName": "getAppliedCampaignAmount",
|
|
7599
7628
|
"signature": "function getProductVariantAppliedCampaignAmount(variant: IkasProductVariant): IkasAppliedCampaignAmount | null",
|
|
7600
|
-
"description": "Get the applied campaign discount amount details for a product variant, including type and formatted value.",
|
|
7629
|
+
"description": "Get the applied campaign discount amount details for a product variant, including type and formatted value.\n\nHow the discount value is interpreted depends on `campaign.type`:\n- `\"FIXED_AMOUNT\"` → the value is an absolute money amount, returned in `formattedPrice` (e.g. \"$10.00\"); `discountPercentage` stays null.\n- `\"RATIO\"` → the value is a percentage, returned in `discountPercentage` (e.g. \"10\" for 10% off); `formattedPrice` stays null.\n\nBoth fixed and tiered campaigns are supported. For a tiered-discount campaign\n(`campaign.fixedDiscount` is null and the discount lives in `campaign.tieredDiscount.rules`),\nthe first tier's amount (`campaign.tieredDiscount.rules[0].amount`) is used, matching the storefront runtime.",
|
|
7601
7630
|
"params": [
|
|
7602
7631
|
{
|
|
7603
7632
|
"name": "variant",
|
|
7604
7633
|
"description": "- The product variant to check for applied campaigns"
|
|
7605
7634
|
}
|
|
7606
7635
|
],
|
|
7607
|
-
"returns": "An object
|
|
7636
|
+
"returns": "An object `{ type, formattedPrice, discountPercentage }` — `formattedPrice` is set for FIXED_AMOUNT campaigns, `discountPercentage` for RATIO campaigns (fixed and tiered alike); the other field stays null. Returns null if no campaign is applied.",
|
|
7608
7637
|
"returnType": "IkasAppliedCampaignAmount | null",
|
|
7609
7638
|
"example": "```typescript\nimport { getProductVariantAppliedCampaignAmount, getSelectedProductVariant } from \"@ikas/bp-storefront\";\nimport { IkasProduct } from \"@ikas/bp-storefront\";\n\nfunction CampaignInfo({ product }: { product: IkasProduct }) {\n const variant = getSelectedProductVariant(product);\n const campaignAmount = getProductVariantAppliedCampaignAmount(variant);\n\n if (!campaignAmount) return null;\n\n return (\n <div>\n {campaignAmount.type === \"RATIO\"\n ? `${campaignAmount.discountPercentage}% off`\n : `${campaignAmount.formattedPrice} off`}\n </div>\n );\n}\n```",
|
|
7610
7639
|
"categories": [
|
|
@@ -7999,6 +8028,36 @@
|
|
|
7999
8028
|
"IkasProductVariant"
|
|
8000
8029
|
]
|
|
8001
8030
|
},
|
|
8031
|
+
{
|
|
8032
|
+
"name": "getProductVariantTieredDiscountProducts",
|
|
8033
|
+
"displayName": "getTieredDiscountProducts",
|
|
8034
|
+
"signature": "function getProductVariantTieredDiscountProducts(variant: IkasProductVariant): IkasTieredDiscountProduct[]",
|
|
8035
|
+
"description": "Get the tiered-discount breakdown for a product variant, one entry per discount tier.\n\nA tiered discount defines multiple quantity tiers (`campaign.tieredDiscount.rules`), each with its own\namount and quantity range. This resolves every tier against the variant's price and returns the\nper-tier sell/final prices (both raw numbers and formatted strings), matching the storefront runtime.\nThe raw rules are `IkasProductTieredDiscountRule` (ranges may be null); this function returns the\nresolved `IkasTieredDiscountProduct` with normalized `{ min, max }` — use the resolved shape, not the raw rule.\n\n`sellPrice`/`finalPrice` (and their `formatted*` variants) are PER UNIT; the `*WithQuantity` fields are the\ntier total for buying the minimum quantity. A `\"FIXED_AMOUNT\"` discount is applied only to that total, so\nper-unit `finalPrice` equals `sellPrice` and the saving shows only in `finalPriceWithQuantity`.\n\nThe discount `amount` is interpreted by `campaign.type`: `\"RATIO\"` treats it as a percentage,\n`\"FIXED_AMOUNT\"` as an absolute money amount subtracted from the tier total. `amount`/`type` are\ninformational — the discount is already applied in the resolved `*Price` fields, so prefer those over\nrecomputing it yourself.\n\n`lineItemQuantityRange.min`/`max` are normalized numbers where `0` means \"unbounded\". In particular\n`max === 0` marks an open-ended top tier (e.g. \"6+\" with no upper limit) — render it as \"min+\" rather\nthan \"min–max\", and never treat `max` as a real quantity when it is `0`.\n\nEach tier's `salesChannelIds` lists the channels it targets (empty/null = all channels). Filter tiers\nagainst `IkasStorefrontConfig.salesChannelId` so only those valid for the current storefront are shown.\n\nReturns an empty array when the variant has no tiered-discount campaign, when a\n`PRODUCT_AND_VARIANT` filter excludes this variant, or when no tier defines a quantity range.",
|
|
8036
|
+
"params": [
|
|
8037
|
+
{
|
|
8038
|
+
"name": "variant",
|
|
8039
|
+
"description": "- The product variant to resolve tiered discounts for"
|
|
8040
|
+
}
|
|
8041
|
+
],
|
|
8042
|
+
"returns": "An array of tier objects (`amount`, `lineItemQuantityRange`, `type`, sell/final prices with their formatted variants, `salesChannelIds`), or an empty array if no tiered discount applies",
|
|
8043
|
+
"returnType": "IkasTieredDiscountProduct[]",
|
|
8044
|
+
"example": "```typescript\nimport {\n getProductVariantTieredDiscountProducts,\n getSelectedProductVariant,\n IkasStorefrontConfig,\n} from \"@ikas/bp-storefront\";\nimport { IkasProduct } from \"@ikas/bp-storefront\";\n\nfunction TieredDiscountTable({ product }: { product: IkasProduct }) {\n const variant = getSelectedProductVariant(product);\n const tiers = getProductVariantTieredDiscountProducts(variant);\n const salesChannelId = IkasStorefrontConfig.salesChannelId;\n\n if (!tiers.length) return null;\n\n return (\n <ul>\n {tiers.map((tier, i) => {\n // A tier applies when it targets no channels or includes the current one\n const scoped =\n !tier.salesChannelIds?.length ||\n (!!salesChannelId && tier.salesChannelIds.includes(salesChannelId));\n if (!scoped) return null;\n\n return (\n <li key={i}>\n Buy {tier.lineItemQuantityRange.min}+ → {tier.formattedFinalPriceWithQuantity}{\" \"}\n <s>{tier.formattedSellPriceWithQuantity}</s>\n </li>\n );\n })}\n </ul>\n );\n}\n```",
|
|
8045
|
+
"categories": [
|
|
8046
|
+
"Pricing",
|
|
8047
|
+
"ProductVariant"
|
|
8048
|
+
],
|
|
8049
|
+
"related": [
|
|
8050
|
+
"getProductVariantAppliedCampaignAmount",
|
|
8051
|
+
"getProductVariantCampaignOffersDiscountPercentage",
|
|
8052
|
+
"getProductVariantFinalPrice"
|
|
8053
|
+
],
|
|
8054
|
+
"isAsync": false,
|
|
8055
|
+
"isClass": false,
|
|
8056
|
+
"parameterTypes": [
|
|
8057
|
+
"IkasProductVariant",
|
|
8058
|
+
"IkasTieredDiscountProduct"
|
|
8059
|
+
]
|
|
8060
|
+
},
|
|
8002
8061
|
{
|
|
8003
8062
|
"name": "getProductVariantIsBackInStockEnabled",
|
|
8004
8063
|
"displayName": "isBackInStockEnabled",
|
|
@@ -9556,7 +9615,7 @@
|
|
|
9556
9615
|
"name": "initAddressForm",
|
|
9557
9616
|
"displayName": "init",
|
|
9558
9617
|
"signature": "async function initAddressForm(addressForm: AddressForm, address?: IkasCustomerAddress): Promise<void>",
|
|
9559
|
-
"description": "Initializes an address form with default or existing address values, loads location data, and configures field settings.",
|
|
9618
|
+
"description": "Initializes an address form with default or existing address values, loads location data, and configures field settings.\n\nAlso resolves `addressForm.addressFormat` for the selected country. That is an\n`AddressFormItem[][]` describing which fields the country uses and how they group into rows\n(outer array = rows, inner array = fields sharing a row), and it is the only correct source\nfor laying out an address form -- a hardcoded field list will be wrong for most countries.\nIt is empty until this promise resolves, and `setAddressFormCountry` re-resolves it, so\nrender from it rather than copying it into local state.",
|
|
9560
9619
|
"params": [
|
|
9561
9620
|
{
|
|
9562
9621
|
"name": "addressForm",
|
|
@@ -9569,7 +9628,7 @@
|
|
|
9569
9628
|
],
|
|
9570
9629
|
"returns": "A promise that resolves once the form is fully initialized, including country/state/city lists, field settings, checkout settings, and shipping zones.",
|
|
9571
9630
|
"returnType": "Promise<void>",
|
|
9572
|
-
"example": "```
|
|
9631
|
+
"example": "```tsx\nimport { useEffect, useState } from \"preact/hooks\";\nimport {\n type AddressForm,\n type AddressFormItem,\n initAddressForm,\n setAddressFormFirstName,\n setAddressFormLastName,\n setAddressFormIdentityNumber,\n setAddressFormAddressLine1,\n setAddressFormAddressLine2,\n setAddressFormPostalCode,\n setAddressFormPhone,\n} from \"@ikas/bp-storefront\";\n\n// Initialize an empty address form\nawait initAddressForm(addressForm);\n\n// Initialize with an existing customer address for editing\nawait initAddressForm(addressForm, existingAddress);\n\n// addressFormat is empty until init resolves, so gate the render on it.\nconst [isLoading, setIsLoading] = useState(true);\nuseEffect(() => {\n initAddressForm(addressForm, address).then(() => setIsLoading(false));\n}, []);\n\n// Every addressFormat key has a matching setter, each taking (addressForm, value).\n// The location keys (country, state, city, district, region) are omitted here: they\n// render as selects fed by addressForm.countryOptions / stateOptions / cityOptions /\n// districtOptions / regionOptions, and must fall back to a text input when the field\n// isFreeText or has no options.\nconst SETTERS: Partial<Record<AddressFormItem, (form: AddressForm, value: string) => void>> = {\n firstName: setAddressFormFirstName,\n lastName: setAddressFormLastName,\n identityNumber: setAddressFormIdentityNumber,\n addressLine1: setAddressFormAddressLine1,\n addressLine2: setAddressFormAddressLine2,\n postalCode: setAddressFormPostalCode,\n phone: setAddressFormPhone,\n};\n\n// Render the country's own layout: outer array = rows, inner array = fields in that row.\n(addressForm.addressFormat ?? []).map((row) => {\n // A field the country does not use is absent from the form object entirely.\n const keys = row.filter((key) => addressForm[key] != null);\n if (!keys.length) return null;\n\n return (\n <div className=\"address-row\" key={keys.join(\"-\")}>\n {keys.map((key) => {\n // Each entry is an IkasFormItem: value, label, placeholder, hasError, message.\n const field = addressForm[key];\n if (!field) return null; // already guaranteed by the filter above; narrows the type\n return (\n <label key={key}>\n {field.label}\n <input\n value={field.value ?? \"\"}\n placeholder={field.placeholder}\n onInput={(e) => SETTERS[key]?.(addressForm, e.currentTarget.value)}\n />\n {field.hasError && <small>{field.message}</small>}\n </label>\n );\n })}\n </div>\n );\n})\n```",
|
|
9573
9632
|
"categories": [
|
|
9574
9633
|
"Address",
|
|
9575
9634
|
"Form",
|
|
@@ -10716,6 +10775,88 @@
|
|
|
10716
10775
|
"isAsync": true,
|
|
10717
10776
|
"isClass": false
|
|
10718
10777
|
},
|
|
10778
|
+
{
|
|
10779
|
+
"name": "initDeactivateCustomerForm",
|
|
10780
|
+
"displayName": "init",
|
|
10781
|
+
"signature": "function initDeactivateCustomerForm(deactivateCustomerForm: DeactivateCustomerForm): void",
|
|
10782
|
+
"description": "Initializes the deactivate customer form with default password field values, labels, and placeholders.",
|
|
10783
|
+
"params": [
|
|
10784
|
+
{
|
|
10785
|
+
"name": "deactivateCustomerForm",
|
|
10786
|
+
"description": "- The deactivate customer form model to initialize"
|
|
10787
|
+
}
|
|
10788
|
+
],
|
|
10789
|
+
"returns": "void",
|
|
10790
|
+
"returnType": "void",
|
|
10791
|
+
"example": "```typescript\nimport { initDeactivateCustomerForm } from \"@ikas/bp-storefront\";\ninitDeactivateCustomerForm(deactivateCustomerForm);\n```",
|
|
10792
|
+
"categories": [
|
|
10793
|
+
"Validation",
|
|
10794
|
+
"DeactivateCustomer",
|
|
10795
|
+
"Form"
|
|
10796
|
+
],
|
|
10797
|
+
"related": [
|
|
10798
|
+
"setDeactivateCustomerFormPassword",
|
|
10799
|
+
"submitDeactivateCustomerForm"
|
|
10800
|
+
],
|
|
10801
|
+
"isAsync": false,
|
|
10802
|
+
"isClass": false
|
|
10803
|
+
},
|
|
10804
|
+
{
|
|
10805
|
+
"name": "setDeactivateCustomerFormPassword",
|
|
10806
|
+
"displayName": "setPassword",
|
|
10807
|
+
"signature": "function setDeactivateCustomerFormPassword(deactivateCustomerForm: DeactivateCustomerForm, value: string): void",
|
|
10808
|
+
"description": "Sets the password value on the deactivate customer form and re-validates if the form has already been submitted.",
|
|
10809
|
+
"params": [
|
|
10810
|
+
{
|
|
10811
|
+
"name": "deactivateCustomerForm",
|
|
10812
|
+
"description": "- The deactivate customer form model to update"
|
|
10813
|
+
},
|
|
10814
|
+
{
|
|
10815
|
+
"name": "value",
|
|
10816
|
+
"description": "- The new password string to set"
|
|
10817
|
+
}
|
|
10818
|
+
],
|
|
10819
|
+
"returns": "void",
|
|
10820
|
+
"returnType": "void",
|
|
10821
|
+
"example": "```typescript\nimport { setDeactivateCustomerFormPassword } from \"@ikas/bp-storefront\";\nsetDeactivateCustomerFormPassword(deactivateCustomerForm, \"mySecurePassword123\");\n```",
|
|
10822
|
+
"categories": [
|
|
10823
|
+
"Validation",
|
|
10824
|
+
"DeactivateCustomer",
|
|
10825
|
+
"Form"
|
|
10826
|
+
],
|
|
10827
|
+
"related": [
|
|
10828
|
+
"initDeactivateCustomerForm",
|
|
10829
|
+
"submitDeactivateCustomerForm"
|
|
10830
|
+
],
|
|
10831
|
+
"isAsync": false,
|
|
10832
|
+
"isClass": false
|
|
10833
|
+
},
|
|
10834
|
+
{
|
|
10835
|
+
"name": "submitDeactivateCustomerForm",
|
|
10836
|
+
"displayName": "submit",
|
|
10837
|
+
"signature": "async function submitDeactivateCustomerForm(deactivateCustomerForm: DeactivateCustomerForm): Promise<boolean>",
|
|
10838
|
+
"description": "Validates and submits the deactivate customer form, deleting the current customer's account after password verification.\nThe customer session is not cleared automatically, call `logout` after a successful submission.",
|
|
10839
|
+
"params": [
|
|
10840
|
+
{
|
|
10841
|
+
"name": "deactivateCustomerForm",
|
|
10842
|
+
"description": "- The deactivate customer form model to submit"
|
|
10843
|
+
}
|
|
10844
|
+
],
|
|
10845
|
+
"returns": "A promise that resolves to true if the account was deactivated successfully, or false on validation error or API failure",
|
|
10846
|
+
"returnType": "Promise<boolean>",
|
|
10847
|
+
"example": "```typescript\nimport { customerStore, logout, submitDeactivateCustomerForm } from \"@ikas/bp-storefront\";\nconst success = await submitDeactivateCustomerForm(deactivateCustomerForm);\nif (success) {\n await logout(customerStore);\n}\n```",
|
|
10848
|
+
"categories": [
|
|
10849
|
+
"Validation",
|
|
10850
|
+
"DeactivateCustomer",
|
|
10851
|
+
"Form"
|
|
10852
|
+
],
|
|
10853
|
+
"related": [
|
|
10854
|
+
"initDeactivateCustomerForm",
|
|
10855
|
+
"setDeactivateCustomerFormPassword"
|
|
10856
|
+
],
|
|
10857
|
+
"isAsync": true,
|
|
10858
|
+
"isClass": false
|
|
10859
|
+
},
|
|
10719
10860
|
{
|
|
10720
10861
|
"name": "initForgotPasswordForm",
|
|
10721
10862
|
"displayName": "init",
|
|
@@ -12559,11 +12700,27 @@
|
|
|
12559
12700
|
"name": "bs_searchProductById",
|
|
12560
12701
|
"displayName": "searchProductById",
|
|
12561
12702
|
"signature": "async function bs_searchProductById(baseStore: BaseStore, params: { productId: string }): Promise<{\n isSuccess: boolean;\n product: IkasProduct | null;\n}>",
|
|
12562
|
-
"description": "",
|
|
12563
|
-
"params": [
|
|
12703
|
+
"description": "Fetches a single product by id and returns it as a full `IkasProduct`.\n\nUse this when a lightweight reference (e.g. a cart line's `IkasOrderLineVariant`, which carries\nneither `salesChannels` nor `stock`) needs product-level data: the returned product includes\n`salesChannels` filtered to the active sales channel (with `minQuantityPerCart` /\n`maxQuantityPerCart`) and per-variant `stock` (summed over the sales channel's configured\nstock locations). `selectedVariantValues` is seeded from the first active variant (or the\nfirst variant when none is active). For multiple ids, prefer `bs_searchProductsById` — one\nbatched request.",
|
|
12704
|
+
"params": [
|
|
12705
|
+
{
|
|
12706
|
+
"name": "baseStore",
|
|
12707
|
+
"description": "- The base store instance"
|
|
12708
|
+
},
|
|
12709
|
+
{
|
|
12710
|
+
"name": "params",
|
|
12711
|
+
"description": "- `{ productId }` — id of the product to fetch"
|
|
12712
|
+
}
|
|
12713
|
+
],
|
|
12714
|
+
"returns": "`{ isSuccess, product }` — `product` is null when not found or on failure",
|
|
12564
12715
|
"returnType": "Promise<{\n isSuccess: boolean;\n product: IkasProduct | null;\n}>",
|
|
12565
|
-
"
|
|
12566
|
-
"
|
|
12716
|
+
"example": "```tsx\nimport { baseStore, bs_searchProductById, IkasStorefrontConfig } from \"@ikas/bp-storefront\";\n\nconst { isSuccess, product } = await bs_searchProductById(baseStore, { productId });\nif (isSuccess && product) {\n const channel = product.salesChannels?.find(sc => sc.id === IkasStorefrontConfig.salesChannelId);\n console.log(channel?.maxQuantityPerCart);\n}\n```",
|
|
12717
|
+
"categories": [
|
|
12718
|
+
"Product",
|
|
12719
|
+
"Search"
|
|
12720
|
+
],
|
|
12721
|
+
"related": [
|
|
12722
|
+
"bs_searchProductsById"
|
|
12723
|
+
],
|
|
12567
12724
|
"isAsync": true,
|
|
12568
12725
|
"isClass": false,
|
|
12569
12726
|
"parameterTypes": [
|
|
@@ -12574,11 +12731,29 @@
|
|
|
12574
12731
|
"name": "bs_searchProductsById",
|
|
12575
12732
|
"displayName": "searchProductsById",
|
|
12576
12733
|
"signature": "async function bs_searchProductsById(baseStore: BaseStore, params: { productIds: string[] }): Promise<{\n isSuccess: boolean;\n products: IkasProduct[] | null;\n}>",
|
|
12577
|
-
"description": "",
|
|
12578
|
-
"params": [
|
|
12734
|
+
"description": "Batch-fetches products by id in a single request and returns them as full `IkasProduct` objects.\n\nThe go-to function when cart lines (or any lightweight reference) need product-level data they\ndo not carry: `IkasOrderLineVariant` has neither `salesChannels` nor `stock`, while the products\nreturned here include `salesChannels` filtered to the active sales channel (with\n`minQuantityPerCart` / `maxQuantityPerCart`) and per-variant `stock` (summed over the sales\nchannel's configured stock locations). Collect the distinct `productId`s of the lines and\nfetch them in ONE call instead of one request per line. Called with an empty `productIds`,\nit returns `{ isSuccess: true, products: [] }` without a network request.",
|
|
12735
|
+
"params": [
|
|
12736
|
+
{
|
|
12737
|
+
"name": "baseStore",
|
|
12738
|
+
"description": "- The base store instance"
|
|
12739
|
+
},
|
|
12740
|
+
{
|
|
12741
|
+
"name": "params",
|
|
12742
|
+
"description": "- `{ productIds }` — product ids to fetch (deduplicate before calling)"
|
|
12743
|
+
}
|
|
12744
|
+
],
|
|
12745
|
+
"returns": "`{ isSuccess, products }` — `products` is null on failure",
|
|
12579
12746
|
"returnType": "Promise<{\n isSuccess: boolean;\n products: IkasProduct[] | null;\n}>",
|
|
12580
|
-
"
|
|
12581
|
-
"
|
|
12747
|
+
"example": "```tsx\nimport { baseStore, bs_searchProductsById, cartStore, IkasStorefrontConfig } from \"@ikas/bp-storefront\";\n\n// Enforce per-cart quantity limits on cart lines:\nconst productIds = [\n ...new Set(\n (cartStore.cart?.orderLineItems ?? [])\n .map(item => item.variant.productId)\n .filter((id): id is string => !!id)\n ),\n];\nconst { products } = await bs_searchProductsById(baseStore, { productIds });\nconst maxByProductId = new Map<string, number | null>();\nfor (const p of products ?? []) {\n const channel = p.salesChannels?.find(sc => sc.id === IkasStorefrontConfig.salesChannelId);\n maxByProductId.set(p.id, channel?.maxQuantityPerCart ?? null);\n}\n```",
|
|
12748
|
+
"categories": [
|
|
12749
|
+
"Product",
|
|
12750
|
+
"Cart",
|
|
12751
|
+
"Search"
|
|
12752
|
+
],
|
|
12753
|
+
"related": [
|
|
12754
|
+
"bs_searchProductById",
|
|
12755
|
+
"changeItemQuantity"
|
|
12756
|
+
],
|
|
12582
12757
|
"isAsync": true,
|
|
12583
12758
|
"isClass": false,
|
|
12584
12759
|
"parameterTypes": [
|
|
@@ -12616,7 +12791,7 @@
|
|
|
12616
12791
|
"name": "addItemToCart",
|
|
12617
12792
|
"displayName": "addVariantToCart",
|
|
12618
12793
|
"signature": "async function addItemToCart(variant: IkasProductVariant, product: IkasProduct, initialQuantity: number = 1, options?: AddItemOptions): Promise<IkasCartOperationResult>",
|
|
12619
|
-
"description": "Add a product variant to the shopping cart.",
|
|
12794
|
+
"description": "Add a product variant to the shopping cart.\n\nClamps the quantity to the sales channel's `minQuantityPerCart`/`maxQuantityPerCart` only\nwhen it creates a new cart line. When the variant already has a line in the cart, the add\nis delegated to `changeItemQuantity` (existing quantity + `initialQuantity`) with no\nclient-side clamp — a quantity past `maxQuantityPerCart` is then rejected by the API with\nthe `MAX_QUANTITY_PER_CART_LIMIT_REACHED` code in `result.response.errorCodes`, never as a\n`validationError`. See `changeItemQuantity` for the handling pattern.",
|
|
12620
12795
|
"params": [
|
|
12621
12796
|
{
|
|
12622
12797
|
"name": "variant",
|
|
@@ -12692,7 +12867,7 @@
|
|
|
12692
12867
|
"name": "changeItemQuantity",
|
|
12693
12868
|
"displayName": "changeQuantityOnCart",
|
|
12694
12869
|
"signature": "async function changeItemQuantity(item: IkasOrderLineItem, quantity: number, offers?: IkasProductOffer[], product?: IkasProduct): Promise<IkasCartOperationResult>",
|
|
12695
|
-
"description": "Change the quantity of an item in the cart.\nUse quantity=0 to remove the item.",
|
|
12870
|
+
"description": "Change the quantity of an item in the cart.\nUse quantity=0 to remove the item.\n\nPerforms no client-side clamping or validation: a quantity above the sales channel's\n`maxQuantityPerCart` is rejected by the API with the `MAX_QUANTITY_PER_CART_LIMIT_REACHED`\ncode in `result.response.errorCodes` (never as a `validationError`). Prevent violations in\nthe stepper and treat the error code as the fallback.",
|
|
12696
12871
|
"params": [
|
|
12697
12872
|
{
|
|
12698
12873
|
"name": "item",
|
|
@@ -12713,7 +12888,7 @@
|
|
|
12713
12888
|
],
|
|
12714
12889
|
"returns": "Result with success flag",
|
|
12715
12890
|
"returnType": "Promise<IkasCartOperationResult>",
|
|
12716
|
-
"example": "```typescript\nimport { cartStore, changeItemQuantity } from \"@ikas/bp-storefront\";\n\n// Increment quantity\nasync function handleIncrement(itemId: string) {\n const item = cartStore.cart?.orderLineItems.find(i => i.id === itemId);\n if (item) {\n const result = await changeItemQuantity(item, item.quantity + 1);\n if (!result.success) {\n showToast(\"Failed to update quantity\");\n }\n }\n}\n\n// Decrement quantity\nasync function handleDecrement(itemId: string) {\n const item = cartStore.cart?.orderLineItems.find(i => i.id === itemId);\n if (item && item.quantity > 1) {\n await changeItemQuantity(item, item.quantity - 1);\n }\n}\n```",
|
|
12891
|
+
"example": "```typescript\nimport { APIErrorCode, cartStore, changeItemQuantity } from \"@ikas/bp-storefront\";\n\n// Increment quantity\nasync function handleIncrement(itemId: string) {\n const item = cartStore.cart?.orderLineItems.find(i => i.id === itemId);\n if (item) {\n const result = await changeItemQuantity(item, item.quantity + 1);\n if (!result.success) {\n const limitHit = result.response?.errorCodes?.includes(\n APIErrorCode.MAX_QUANTITY_PER_CART_LIMIT_REACHED\n );\n showToast(limitHit ? \"Per-cart quantity limit reached\" : \"Failed to update quantity\");\n }\n }\n}\n\n// Decrement quantity\nasync function handleDecrement(itemId: string) {\n const item = cartStore.cart?.orderLineItems.find(i => i.id === itemId);\n if (item && item.quantity > 1) {\n await changeItemQuantity(item, item.quantity - 1);\n }\n}\n```",
|
|
12717
12892
|
"categories": [
|
|
12718
12893
|
"Cart"
|
|
12719
12894
|
],
|
|
@@ -13022,6 +13197,37 @@
|
|
|
13022
13197
|
"IkasCartOperationResult"
|
|
13023
13198
|
]
|
|
13024
13199
|
},
|
|
13200
|
+
{
|
|
13201
|
+
"name": "removeGiftCardLine",
|
|
13202
|
+
"signature": "async function removeGiftCardLine(cart: IkasCart, giftCardId?: string | null): Promise<IkasCartOperationResult>",
|
|
13203
|
+
"description": "Remove a gift card (or store credit) line from the cart.\n\nGift cards are applied through `saveCouponCode` with the gift card code, and the applied\ncards are listed on `cart.giftCardLines`. Pass the `giftCardId` of the line to remove; when\nomitted, every gift card line is removed from the cart.",
|
|
13204
|
+
"params": [
|
|
13205
|
+
{
|
|
13206
|
+
"name": "cart",
|
|
13207
|
+
"description": "- The cart object"
|
|
13208
|
+
},
|
|
13209
|
+
{
|
|
13210
|
+
"name": "giftCardId",
|
|
13211
|
+
"description": "- The gift card to remove, or null/undefined to remove all of them"
|
|
13212
|
+
}
|
|
13213
|
+
],
|
|
13214
|
+
"returns": "Result with success flag",
|
|
13215
|
+
"returnType": "Promise<IkasCartOperationResult>",
|
|
13216
|
+
"example": "```typescript\nimport { cartStore, removeGiftCardLine } from \"@ikas/bp-storefront\";\n\nasync function handleRemoveGiftCard(giftCardId: string) {\n if (!cartStore.cart) return;\n\n const result = await removeGiftCardLine(cartStore.cart, giftCardId);\n if (result.success) {\n showToast(\"Gift card removed\");\n }\n}\n```",
|
|
13217
|
+
"categories": [
|
|
13218
|
+
"Cart"
|
|
13219
|
+
],
|
|
13220
|
+
"related": [
|
|
13221
|
+
"saveCouponCode",
|
|
13222
|
+
"getIkasOrderGiftCardTotalPrice"
|
|
13223
|
+
],
|
|
13224
|
+
"isAsync": true,
|
|
13225
|
+
"isClass": false,
|
|
13226
|
+
"parameterTypes": [
|
|
13227
|
+
"IkasCart",
|
|
13228
|
+
"IkasCartOperationResult"
|
|
13229
|
+
]
|
|
13230
|
+
},
|
|
13025
13231
|
{
|
|
13026
13232
|
"name": "getCart",
|
|
13027
13233
|
"signature": "async function getCart(): Promise<void>",
|
|
@@ -13922,7 +14128,8 @@
|
|
|
13922
14128
|
],
|
|
13923
14129
|
"related": [
|
|
13924
14130
|
"hasCustomer",
|
|
13925
|
-
"logout"
|
|
14131
|
+
"logout",
|
|
14132
|
+
"getDeactivateCustomerForm"
|
|
13926
14133
|
],
|
|
13927
14134
|
"isAsync": true,
|
|
13928
14135
|
"isClass": false,
|
|
@@ -14493,6 +14700,58 @@
|
|
|
14493
14700
|
"IkasCustomerStore"
|
|
14494
14701
|
]
|
|
14495
14702
|
},
|
|
14703
|
+
{
|
|
14704
|
+
"name": "getDeactivateCustomerForm",
|
|
14705
|
+
"signature": "function getDeactivateCustomerForm(customerStore: IkasCustomerStore): DeactivateCustomerForm",
|
|
14706
|
+
"description": "Get or initialize the deactivate customer form with validation for deleting the current customer's account.",
|
|
14707
|
+
"params": [
|
|
14708
|
+
{
|
|
14709
|
+
"name": "customerStore",
|
|
14710
|
+
"description": "- The customer store instance"
|
|
14711
|
+
}
|
|
14712
|
+
],
|
|
14713
|
+
"returns": "The deactivate customer form object with validated fields",
|
|
14714
|
+
"returnType": "DeactivateCustomerForm",
|
|
14715
|
+
"example": "```typescript\nimport {\n customerStore,\n getDeactivateCustomerForm,\n setDeactivateCustomerFormPassword,\n submitDeactivateCustomerForm,\n logout,\n} from \"@ikas/bp-storefront\";\n\nfunction DeleteAccountPage() {\n const form = getDeactivateCustomerForm(customerStore);\n\n const handleSubmit = async () => {\n const isSuccess = await submitDeactivateCustomerForm(form);\n if (isSuccess) {\n await logout(customerStore);\n Router.navigateToPage(\"INDEX\");\n }\n };\n\n return (\n <form>\n <input\n type=\"password\"\n value={form.password.value}\n onChange={e => setDeactivateCustomerFormPassword(form, e.target.value)}\n />\n <button onClick={handleSubmit}>Delete Account</button>\n </form>\n );\n}\n```",
|
|
14716
|
+
"categories": [
|
|
14717
|
+
"Customer",
|
|
14718
|
+
"Account"
|
|
14719
|
+
],
|
|
14720
|
+
"related": [
|
|
14721
|
+
"clearDeactivateCustomerForm",
|
|
14722
|
+
"deactivateCustomer"
|
|
14723
|
+
],
|
|
14724
|
+
"isAsync": false,
|
|
14725
|
+
"isClass": false,
|
|
14726
|
+
"parameterTypes": [
|
|
14727
|
+
"IkasCustomerStore"
|
|
14728
|
+
]
|
|
14729
|
+
},
|
|
14730
|
+
{
|
|
14731
|
+
"name": "clearDeactivateCustomerForm",
|
|
14732
|
+
"signature": "function clearDeactivateCustomerForm(customerStore: IkasCustomerStore): void",
|
|
14733
|
+
"description": "Clear the cached deactivate customer form, forcing a fresh form on next retrieval.",
|
|
14734
|
+
"params": [
|
|
14735
|
+
{
|
|
14736
|
+
"name": "customerStore",
|
|
14737
|
+
"description": "- The customer store instance"
|
|
14738
|
+
}
|
|
14739
|
+
],
|
|
14740
|
+
"returnType": "void",
|
|
14741
|
+
"example": "```typescript\nimport { customerStore, clearDeactivateCustomerForm } from \"@ikas/bp-storefront\";\n\nfunction handleDeactivateCustomerReset() {\n clearDeactivateCustomerForm(customerStore);\n}\n```",
|
|
14742
|
+
"categories": [
|
|
14743
|
+
"Customer",
|
|
14744
|
+
"Account"
|
|
14745
|
+
],
|
|
14746
|
+
"related": [
|
|
14747
|
+
"getDeactivateCustomerForm"
|
|
14748
|
+
],
|
|
14749
|
+
"isAsync": false,
|
|
14750
|
+
"isClass": false,
|
|
14751
|
+
"parameterTypes": [
|
|
14752
|
+
"IkasCustomerStore"
|
|
14753
|
+
]
|
|
14754
|
+
},
|
|
14496
14755
|
{
|
|
14497
14756
|
"name": "getForgotPasswordForm",
|
|
14498
14757
|
"signature": "function getForgotPasswordForm(customerStore: IkasCustomerStore): ForgotPasswordForm",
|
|
@@ -14862,7 +15121,7 @@
|
|
|
14862
15121
|
{
|
|
14863
15122
|
"name": "getEmptyAddressForm",
|
|
14864
15123
|
"signature": "function getEmptyAddressForm(customerStore: IkasCustomerStore): AddressForm",
|
|
14865
|
-
"description": "Create and return a new, empty address form with validation, wrapped in MobX observability.",
|
|
15124
|
+
"description": "Create and return a new, empty address form with validation, wrapped in MobX observability.\n\nUse this to create an address; use `getIkasCustomerAddressForm(address)` to edit an existing\none. It starts `initAddressForm` internally but does not await it, so await `initAddressForm`\nyourself when you need to know that the country layout (`addressFormat`) and the country/state/\ncity lists are ready to render.",
|
|
14866
15125
|
"params": [
|
|
14867
15126
|
{
|
|
14868
15127
|
"name": "customerStore",
|
|
@@ -14871,14 +15130,16 @@
|
|
|
14871
15130
|
],
|
|
14872
15131
|
"returns": "A new observable address form object with validated fields",
|
|
14873
15132
|
"returnType": "AddressForm",
|
|
14874
|
-
"example": "```
|
|
15133
|
+
"example": "```tsx\nimport {\n customerStore,\n getEmptyAddressForm,\n initAddressForm,\n setAddressFormAddressLine1,\n submitAddressForm,\n} from \"@ikas/bp-storefront\";\n\n// Create the form once, then await init before rendering the country-driven layout.\nconst [form] = useState(() => getEmptyAddressForm(customerStore));\nconst [isLoading, setIsLoading] = useState(true);\nuseEffect(() => {\n initAddressForm(form).then(() => setIsLoading(false));\n}, []);\n\n// Always go through the setters. Assigning `form.addressLine1.value` directly skips\n// re-validation and the dependent-field resets the location setters perform.\nsetAddressFormAddressLine1(form, \"123 Main Street\");\n\n// submitAddressForm validates and saves the address onto the customer itself --\n// do not hand-build a customer object and call saveCustomer for this.\nconst ok = await submitAddressForm(form);\n```",
|
|
14875
15134
|
"categories": [
|
|
14876
15135
|
"Customer",
|
|
14877
15136
|
"Address"
|
|
14878
15137
|
],
|
|
14879
15138
|
"related": [
|
|
14880
|
-
"
|
|
14881
|
-
"
|
|
15139
|
+
"initAddressForm",
|
|
15140
|
+
"submitAddressForm",
|
|
15141
|
+
"getIkasCustomerAddressForm",
|
|
15142
|
+
"deleteCustomerAddress"
|
|
14882
15143
|
],
|
|
14883
15144
|
"isAsync": false,
|
|
14884
15145
|
"isClass": false,
|
|
@@ -15116,6 +15377,128 @@
|
|
|
15116
15377
|
"isClass": true,
|
|
15117
15378
|
"className": "Router"
|
|
15118
15379
|
},
|
|
15380
|
+
{
|
|
15381
|
+
"name": "withRoutePrefix",
|
|
15382
|
+
"signature": "function withRoutePrefix(path: string): string",
|
|
15383
|
+
"description": "Put the visitor's storefront routing in front of a path you wrote yourself.\n\nEntity links (`getProductHref`, `getIkasOrderHref`, …) and LINK props already carry the prefix.\nA literal path in your own markup does not: `href=\"/cart\"` sends a visitor browsing `/en` to the\ndefault language. Wrap it, and a store with no extra routings gets the path back unchanged.\n\nIdempotent — a path that already starts with a supported routing segment is returned as-is.\nAnything that is not a path on this storefront — an absolute URL, `mailto:`, `tel:` — is returned\nuntouched, so a merchant-authored prop can be wrapped without checking it first.",
|
|
15384
|
+
"params": [
|
|
15385
|
+
{
|
|
15386
|
+
"name": "path",
|
|
15387
|
+
"description": "- A path on this storefront, starting with `/`"
|
|
15388
|
+
}
|
|
15389
|
+
],
|
|
15390
|
+
"returns": "The path under the current routing (e.g. `/cart` → `/en/cart`)",
|
|
15391
|
+
"returnType": "string",
|
|
15392
|
+
"example": "```tsx\nimport { Router, withRoutePrefix } from \"@ikas/bp-storefront\";\n\n// Correct href for crawlers, middle-click and open-in-new-tab...\n<a href={withRoutePrefix(\"/cart\")} onClick={e => {\n e.preventDefault();\n Router.navigateToPage(\"CART\"); // ...and this prefixes on its own.\n}}>Cart</a>\n```",
|
|
15393
|
+
"categories": [
|
|
15394
|
+
"Navigation"
|
|
15395
|
+
],
|
|
15396
|
+
"related": [
|
|
15397
|
+
"navigate",
|
|
15398
|
+
"navigateToPage"
|
|
15399
|
+
],
|
|
15400
|
+
"isAsync": false,
|
|
15401
|
+
"isClass": false
|
|
15402
|
+
},
|
|
15403
|
+
{
|
|
15404
|
+
"name": "registerThemeSettingValues",
|
|
15405
|
+
"signature": "function registerThemeSettingValues(values: Record<string, any> | null): void",
|
|
15406
|
+
"description": "Register the live global-variable object (`_g_`) so `getThemeSetting`/`getThemeSettings`\nreturn actual runtime values (constants, computed getters, and in-editor edits) instead\nof the serialized design-time defaults. Called by generated code, not by component authors.",
|
|
15407
|
+
"params": [],
|
|
15408
|
+
"returnType": "void",
|
|
15409
|
+
"categories": [],
|
|
15410
|
+
"related": [],
|
|
15411
|
+
"isAsync": false,
|
|
15412
|
+
"isClass": false
|
|
15413
|
+
},
|
|
15414
|
+
{
|
|
15415
|
+
"name": "getThemeSettings",
|
|
15416
|
+
"signature": "function getThemeSettings(): ThemeSetting[]",
|
|
15417
|
+
"description": "All global variables (Theme Settings) defined for the theme.",
|
|
15418
|
+
"params": [],
|
|
15419
|
+
"returnType": "ThemeSetting[]",
|
|
15420
|
+
"categories": [],
|
|
15421
|
+
"related": [],
|
|
15422
|
+
"isAsync": false,
|
|
15423
|
+
"isClass": false
|
|
15424
|
+
},
|
|
15425
|
+
{
|
|
15426
|
+
"name": "getThemeSetting",
|
|
15427
|
+
"signature": "function getThemeSetting(name: string): ThemeSetting | undefined",
|
|
15428
|
+
"description": "A single global variable by its stable key (`variableName`, e.g. `_6Q0KV7VGGM`).\nDiscover keys via (each item carries a human `displayName`).\nThe returned `value` is the live blueprint value when available, else the default.\nIts shape is discriminated by `type` (see ); note an\nIMAGE setting's value is an image REFERENCE (no `.url`) — resolve with\n`getDefaultSrc`/`getSrc`.",
|
|
15429
|
+
"params": [],
|
|
15430
|
+
"returnType": "ThemeSetting | undefined",
|
|
15431
|
+
"categories": [],
|
|
15432
|
+
"related": [],
|
|
15433
|
+
"isAsync": false,
|
|
15434
|
+
"isClass": false
|
|
15435
|
+
},
|
|
15436
|
+
{
|
|
15437
|
+
"name": "getThemeSettingValue",
|
|
15438
|
+
"signature": "function getThemeSettingValue(name: string): any",
|
|
15439
|
+
"description": "Convenience: the resolved value of a global variable, or `undefined` if not found.",
|
|
15440
|
+
"params": [],
|
|
15441
|
+
"returnType": "any",
|
|
15442
|
+
"categories": [],
|
|
15443
|
+
"related": [],
|
|
15444
|
+
"isAsync": false,
|
|
15445
|
+
"isClass": false
|
|
15446
|
+
},
|
|
15447
|
+
{
|
|
15448
|
+
"name": "getThemeColors",
|
|
15449
|
+
"signature": "function getThemeColors(): RuntimeDesignToken[]",
|
|
15450
|
+
"description": "Theme color tokens. Each carries a resolved value and a `var(--id)` CSS reference.",
|
|
15451
|
+
"params": [],
|
|
15452
|
+
"returnType": "RuntimeDesignToken[]",
|
|
15453
|
+
"categories": [],
|
|
15454
|
+
"related": [],
|
|
15455
|
+
"isAsync": false,
|
|
15456
|
+
"isClass": false
|
|
15457
|
+
},
|
|
15458
|
+
{
|
|
15459
|
+
"name": "getThemeTypography",
|
|
15460
|
+
"signature": "function getThemeTypography(): RuntimeTypographyToken[]",
|
|
15461
|
+
"description": "Theme typography tokens (text styles). Apply `className` or read `resolved` CSS values.",
|
|
15462
|
+
"params": [],
|
|
15463
|
+
"returnType": "RuntimeTypographyToken[]",
|
|
15464
|
+
"categories": [],
|
|
15465
|
+
"related": [],
|
|
15466
|
+
"isAsync": false,
|
|
15467
|
+
"isClass": false
|
|
15468
|
+
},
|
|
15469
|
+
{
|
|
15470
|
+
"name": "getThemeBreakpoints",
|
|
15471
|
+
"signature": "function getThemeBreakpoints(): RuntimeBreakpointToken[]",
|
|
15472
|
+
"description": "Theme responsive breakpoints (`{ id, width }`).",
|
|
15473
|
+
"params": [],
|
|
15474
|
+
"returnType": "RuntimeBreakpointToken[]",
|
|
15475
|
+
"categories": [],
|
|
15476
|
+
"related": [],
|
|
15477
|
+
"isAsync": false,
|
|
15478
|
+
"isClass": false
|
|
15479
|
+
},
|
|
15480
|
+
{
|
|
15481
|
+
"name": "getThemeKeyframes",
|
|
15482
|
+
"signature": "function getThemeKeyframes(): RuntimeKeyframeToken[]",
|
|
15483
|
+
"description": "Theme keyframe/transition animations. Use `ref` as the CSS animation name.",
|
|
15484
|
+
"params": [],
|
|
15485
|
+
"returnType": "RuntimeKeyframeToken[]",
|
|
15486
|
+
"categories": [],
|
|
15487
|
+
"related": [],
|
|
15488
|
+
"isAsync": false,
|
|
15489
|
+
"isClass": false
|
|
15490
|
+
},
|
|
15491
|
+
{
|
|
15492
|
+
"name": "getThemeColorSchemes",
|
|
15493
|
+
"signature": "function getThemeColorSchemes(): RuntimeThemeColorSchemes",
|
|
15494
|
+
"description": "Theme color schemes (palettes). Returns two PARALLEL lists with different jobs:\n- `schemes`: the color SLOTS as `{ id }` only — no colors and no display label live here at\n runtime. A slot's human name is authoring-only (read it via the CLI/MCP `list-theme-globals`\n or the editor); at runtime identify a slot solely by its `id`.\n- `values`: the actual palettes. A palette's colors live in its `colorsByScheme`\n map, keyed by slot id → `{ resolved, cssVar }`.\n\nTo render swatches, iterate `values[].colorsByScheme` (the source of truth for\ncolors), NOT the top-level `schemes` array — `schemes` carries slot ids only, so\niterating it renders empty:\n\n const { values } = getThemeColorSchemes();\n values.forEach(palette =>\n Object.entries(palette.colorsByScheme).forEach(([slotId, { resolved, cssVar }]) => {\n // slotId → stable slot key, cssVar → live var() ref (prefer this), resolved → hex snapshot\n })\n );",
|
|
15495
|
+
"params": [],
|
|
15496
|
+
"returnType": "RuntimeThemeColorSchemes",
|
|
15497
|
+
"categories": [],
|
|
15498
|
+
"related": [],
|
|
15499
|
+
"isAsync": false,
|
|
15500
|
+
"isClass": false
|
|
15501
|
+
},
|
|
15119
15502
|
{
|
|
15120
15503
|
"name": "isBrowser",
|
|
15121
15504
|
"signature": "function isBrowser(yes?: () => void, no?: () => void): void",
|
|
@@ -15142,6 +15525,38 @@
|
|
|
15142
15525
|
"IkasComponentRendererProps"
|
|
15143
15526
|
]
|
|
15144
15527
|
},
|
|
15528
|
+
{
|
|
15529
|
+
"name": "formatCurrency",
|
|
15530
|
+
"signature": "function formatCurrency(price: number, currencyCode: string, currencySymbol: string | null): string",
|
|
15531
|
+
"description": "Format a free-standing amount with the merchant's currency format settings. Use this for\namounts that are NOT tied to a model (remaining amount to free shipping, gift wrap threshold,\nbulk discount limits, cart limit warnings). For model-bound prices, prefer the\n`get*FormattedPrice` helpers — they call this function internally.\n\nApplies the merchant's `currencyFormats` entry for the given currency code (symbol,\nsymbolPosition, thousandSeparator, decimalSeparator, omitZeroDecimal). Behavior details:\nalways two decimal places, and a space between the symbol and the number. `omitZeroDecimal`\ndrops the fraction only when it is exactly `00`.\n\nDo NOT use `Intl.NumberFormat` for currency — it falls back to the browser locale and\nproduces a format that conflicts with platform-formatted prices on the same screen.",
|
|
15532
|
+
"params": [
|
|
15533
|
+
{
|
|
15534
|
+
"name": "price",
|
|
15535
|
+
"description": "- The amount to format"
|
|
15536
|
+
},
|
|
15537
|
+
{
|
|
15538
|
+
"name": "currencyCode",
|
|
15539
|
+
"description": "- Currency code used to look up the merchant format settings (e.g. \"TRY\", \"USD\")"
|
|
15540
|
+
},
|
|
15541
|
+
{
|
|
15542
|
+
"name": "currencySymbol",
|
|
15543
|
+
"description": "- Fallback symbol used when the merchant has no format entry for the code.\nAlways pass the symbol from the model you took the amount from (e.g. `cart.currencySymbol`) —\npassing `null` can render the amount with no symbol at all."
|
|
15544
|
+
}
|
|
15545
|
+
],
|
|
15546
|
+
"returns": "The amount formatted with the merchant's currency format (e.g. \"₺ 1,950.00\")",
|
|
15547
|
+
"returnType": "string",
|
|
15548
|
+
"example": "```typescript\nimport { cartStore, formatCurrency } from \"@ikas/bp-storefront\";\n\nfunction FreeShippingBar({ threshold }: { threshold: number }) {\n const cart = cartStore.cart;\n if (!cart) return null;\n\n const remaining = threshold - cart.totalFinalPrice;\n if (remaining <= 0) return <span>Free shipping unlocked!</span>;\n\n return <span>Add {formatCurrency(remaining, cart.currencyCode, cart.currencySymbol)} more for free shipping</span>;\n}\n```",
|
|
15549
|
+
"categories": [
|
|
15550
|
+
"Pricing"
|
|
15551
|
+
],
|
|
15552
|
+
"related": [
|
|
15553
|
+
"getProductVariantFormattedFinalPrice",
|
|
15554
|
+
"getOrderLineItemFormattedFinalPrice",
|
|
15555
|
+
"getIkasOrderFormattedTotalFinalPrice"
|
|
15556
|
+
],
|
|
15557
|
+
"isAsync": false,
|
|
15558
|
+
"isClass": false
|
|
15559
|
+
},
|
|
15145
15560
|
{
|
|
15146
15561
|
"name": "httpRequest",
|
|
15147
15562
|
"signature": "async function httpRequest(url: string, method: HttpMethod, body?: Record<string, any>, headers?: Record<string, string>): Promise<FetchResponse>",
|
|
@@ -15196,6 +15611,55 @@
|
|
|
15196
15611
|
"related": [],
|
|
15197
15612
|
"isAsync": false,
|
|
15198
15613
|
"isClass": false
|
|
15614
|
+
},
|
|
15615
|
+
{
|
|
15616
|
+
"name": "PayWithIkas",
|
|
15617
|
+
"signature": "function PayWithIkas({ product, quantity = 1, className, style }: PayWithIkasProps): VNode<ClassAttributes<HTMLIFrameElement> & { ref: MutableRef<HTMLIFrameElement | null>; title: string; ... 4 more ...; style: { ...; }; }> | null",
|
|
15618
|
+
"description": "\"Pay with ikas\" (Hızlı Öde) fast-checkout button for the product detail page.\nDrop-in Preact component that renders the pay-with-ikas checkout iframe and\nwires up its whole message protocol, so a theme gets the one-click \"Hızlı Öde\"\nflow without owning any of the plumbing. Use it next to the add-to-cart button\non the product detail page.\n\nThe pay-with-ikas URL is read from `IkasStorefrontConfig.getPayWithIkasUrl()`;\nwhen the merchant has not enabled Pay with ikas the component renders nothing.\nThe add-to-cart-enabled state is tracked reactively via mobx `autorun`, so the\niframe stays in sync as the product's availability changes (e.g. variant\nselection). Clicking \"Hızlı Öde\" creates a temporary cart via\n`createPayWithIkasSession` and redirects to the returned pay URL.",
|
|
15619
|
+
"params": [
|
|
15620
|
+
{
|
|
15621
|
+
"name": "product",
|
|
15622
|
+
"description": "- The product to fast-checkout via Pay with ikas"
|
|
15623
|
+
},
|
|
15624
|
+
{
|
|
15625
|
+
"name": "quantity",
|
|
15626
|
+
"description": "- Quantity to purchase (defaults to 1)"
|
|
15627
|
+
},
|
|
15628
|
+
{
|
|
15629
|
+
"name": "className",
|
|
15630
|
+
"description": "- Optional CSS class applied to the iframe"
|
|
15631
|
+
},
|
|
15632
|
+
{
|
|
15633
|
+
"name": "style",
|
|
15634
|
+
"description": "- Optional inline styles applied to the iframe"
|
|
15635
|
+
}
|
|
15636
|
+
],
|
|
15637
|
+
"returnType": "VNode<ClassAttributes<HTMLIFrameElement> & { ref: MutableRef<HTMLIFrameElement | null>; title: string; ... 4 more ...; style: { ...; }; }> | null",
|
|
15638
|
+
"example": "```tsx\nimport { PayWithIkas } from \"@ikas/bp-storefront\";\n\n// On the product detail page, alongside the add-to-cart button:\n<PayWithIkas product={product} quantity={quantity} />\n```",
|
|
15639
|
+
"categories": [
|
|
15640
|
+
"ProductDetail",
|
|
15641
|
+
"Checkout"
|
|
15642
|
+
],
|
|
15643
|
+
"related": [
|
|
15644
|
+
"createPayWithIkasSession",
|
|
15645
|
+
"isAddToCartEnabled"
|
|
15646
|
+
],
|
|
15647
|
+
"isAsync": false,
|
|
15648
|
+
"isClass": false,
|
|
15649
|
+
"parameterTypes": [
|
|
15650
|
+
"IkasProps"
|
|
15651
|
+
]
|
|
15652
|
+
},
|
|
15653
|
+
{
|
|
15654
|
+
"name": "normalizeSvg",
|
|
15655
|
+
"signature": "function normalizeSvg(svg: string, options: NormalizeSvgOptions): string",
|
|
15656
|
+
"description": "Isomorphic, DOM-free normalization of a raw SVG markup string for render.\nSafe to call in SSR, browser, and node — pure string transforms only.",
|
|
15657
|
+
"params": [],
|
|
15658
|
+
"returnType": "string",
|
|
15659
|
+
"categories": [],
|
|
15660
|
+
"related": [],
|
|
15661
|
+
"isAsync": false,
|
|
15662
|
+
"isClass": false
|
|
15199
15663
|
}
|
|
15200
15664
|
],
|
|
15201
15665
|
"codeExamples": []
|