efficient-storefront-blocks 0.87.0 → 0.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/chunks/{EditorPreviewCheckout-GD4IJ4WK.js → EditorPreviewCheckout-R7XG75DW.js} +1 -1
- package/dist/chunks/{SiteEditorProvider-2UVCJZXS.js → SiteEditorProvider-YNUCDQ2D.js} +1 -1
- package/dist/chunks/chunk-BYBBZS7L.js +1 -0
- package/dist/chunks/{chunk-H4IHUSCU.js → chunk-E54FFOUS.js} +1 -1
- package/dist/chunks/chunk-G4Y7XXRV.js +1 -0
- package/dist/chunks/chunk-WRDUOJZO.js +382 -0
- package/dist/chunks/{fitment-data-5GBUMO2O.js → fitment-data-URBK335I.js} +1 -1
- package/dist/contract.js +14 -2
- package/dist/editor/components/CategorySource.d.ts +8 -1
- package/dist/editor/components/CategorySource.js +1 -1
- package/dist/editor/components/CollectionPicker.js +1 -1
- package/dist/editor/components/EditProductLink.js +1 -1
- package/dist/editor/components/FinishPicker.js +1 -1
- package/dist/editor/components/FormPicker.js +1 -1
- package/dist/editor/components/GalleryShowcaseSource.js +1 -1
- package/dist/editor/components/HeaderSettingsPanel.js +1 -1
- package/dist/editor/components/ProductHeroSource.js +1 -1
- package/dist/editor/components/ProductPicker.js +1 -1
- package/dist/editor/components/ReviewsProductSource.js +1 -1
- package/dist/editor/components/SocialLinksDoor.js +1 -1
- package/dist/editor/components/SpecTableSource.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/BundleOffer/fields.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/FilterBlock/fields.d.ts +2 -0
- package/dist/editor/lib/document/blocks/commerce/FilterBlock/fields.js +1 -0
- package/dist/editor/lib/document/blocks/commerce/FilterChipsBlock/fields.d.ts +2 -0
- package/dist/editor/lib/document/blocks/commerce/FilterChipsBlock/fields.js +1 -0
- package/dist/editor/lib/document/blocks/commerce/GalleryItem/fields.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/ProductBuyButton/fields.d.ts +2 -0
- package/dist/editor/lib/document/blocks/commerce/ProductBuyButton/fields.js +1 -0
- package/dist/editor/lib/document/blocks/commerce/ProductGrid/fields.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/ProductName/fields.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/ProductPicture/fields.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/controls.d.ts +4 -0
- package/dist/editor/lib/document/blocks/commerce/controls.js +1 -1
- package/dist/editor/lib/document/blocks/commerce/index.d.ts +1 -1
- package/dist/editor/lib/document/blocks/commerce/index.js +1 -1
- package/dist/editor/lib/document/config.js +1 -1
- package/dist/editor/lib/editor-words-kept.d.ts +1 -0
- package/dist/editor/lib/editor-words-kept.js +1 -0
- package/dist/editor/lib/efficient-backend.d.ts +6 -1
- package/dist/editor/lib/efficient-backend.js +1 -1
- package/dist/editor/lib/storefront-document.js +1 -1
- package/dist/editor/lib/storefront-editor-words.d.ts +33 -4
- package/dist/editor/lib/storefront-editor-words.js +1 -1
- package/dist/editor.css +1 -1
- package/dist/index.js +134 -81
- package/dist/links.js +1 -1
- package/dist/render/app/globals.css +111 -0
- package/dist/render/built-with.json +1 -1
- package/dist/render/components/BundleCard.d.ts +2 -1
- package/dist/render/components/BundleCard.js +1 -1
- package/dist/render/components/GalleryGrid.js +1 -1
- package/dist/render/components/GalleryItem.d.ts +11 -1
- package/dist/render/components/GalleryItem.js +1 -1
- package/dist/render/components/GridCardTemplate.d.ts +7 -1
- package/dist/render/components/GridCardTemplate.js +1 -1
- package/dist/render/components/ProductGridSection.d.ts +5 -1
- package/dist/render/components/ProductGridSection.js +1 -1
- package/dist/render/components/ProductHeroPanel.js +1 -1
- package/dist/render/components/ProductRef.d.ts +8 -2
- package/dist/render/components/ProductRef.js +1 -1
- package/dist/render/components/SectionBand.d.ts +3 -2
- package/dist/render/components/SectionBand.js +1 -1
- package/dist/render/components/card-pieces/CardBuyButton.d.ts +8 -1
- package/dist/render/components/card-pieces/CardBuyButton.js +1 -1
- package/dist/render/components/card-pieces/CardName.d.ts +2 -1
- package/dist/render/components/card-pieces/CardName.js +1 -1
- package/dist/render/components/card-pieces/CardPrice.js +1 -1
- package/dist/render/components/card-pieces/CardProductBadge.d.ts +2 -1
- package/dist/render/components/card-pieces/CardProductBadge.js +1 -1
- package/dist/render/components/card-pieces/CardProductPicture.d.ts +5 -0
- package/dist/render/components/card-pieces/CardProductPicture.js +1 -1
- package/dist/render/components/card-pieces/CardSpecs.js +1 -1
- package/dist/render/components/card-pieces/HostPart.js +1 -1
- package/dist/render/components/card-pieces/ProductCardState.d.ts +25 -6
- package/dist/render/components/card-pieces/ProductCardState.js +1 -1
- package/dist/render/components/catalog/CatalogFilterContext.d.ts +4 -1
- package/dist/render/components/catalog/CatalogFilterContext.js +1 -1
- package/dist/render/components/catalog/ClearAllButton.d.ts +4 -0
- package/dist/render/components/catalog/ClearAllButton.js +1 -0
- package/dist/render/components/catalog/FilterPill.d.ts +4 -2
- package/dist/render/components/catalog/FilterPill.js +1 -1
- package/dist/render/components/catalog/ShopperChips.d.ts +13 -0
- package/dist/render/components/catalog/ShopperChips.js +1 -0
- package/dist/render/components/catalog/ShopperFilters.d.ts +20 -0
- package/dist/render/components/catalog/ShopperFilters.js +1 -0
- package/dist/render/components/catalog/ShopperScope.d.ts +72 -0
- package/dist/render/components/catalog/ShopperScope.js +3 -0
- package/dist/render/components/catalog/SortSelect.js +1 -1
- package/dist/render/components/pdp-dynamic/DynamicRelatedProducts.js +1 -1
- package/dist/render/components/wheels-plp/PlpActiveChips.js +1 -1
- package/dist/render/components/wheels-plp/PlpPagination.d.ts +2 -1
- package/dist/render/components/wheels-plp/PlpPagination.js +1 -1
- package/dist/render/components/wheels-plp/PlpSidebar.js +1 -1
- package/dist/render/components/wheels-plp/usePlpFiltersInUrl.d.ts +2 -0
- package/dist/render/components/wheels-plp/usePlpFiltersInUrl.js +1 -1
- package/dist/render/lib/api/index.d.ts +6 -0
- package/dist/render/lib/api/index.js +1 -1
- package/dist/render/lib/catalog/related-cards.d.ts +4 -1
- package/dist/render/lib/catalog/relationships.d.ts +9 -2
- package/dist/render/lib/catalog/relationships.js +1 -1
- package/dist/render/lib/commerce.d.ts +2 -0
- package/dist/render/lib/commerce.js +1 -1
- package/dist/render/lib/content/article-body.js +1 -5
- package/dist/render/lib/content/filter-card-seed.d.ts +10 -0
- package/dist/render/lib/content/filter-card-seed.js +1 -0
- package/dist/render/lib/content/product-card-seed.d.ts +5 -0
- package/dist/render/lib/content/product-card-seed.js +1 -1
- package/dist/render/lib/document/blocks/commerce/BundleOffer/meta.js +1 -1
- package/dist/render/lib/document/blocks/commerce/BundleOffer/render.js +1 -1
- package/dist/render/lib/document/blocks/commerce/FilterBlock/meta.d.ts +8 -0
- package/dist/render/lib/document/blocks/commerce/FilterBlock/meta.js +1 -0
- package/dist/render/lib/document/blocks/commerce/FilterBlock/render.d.ts +2 -0
- package/dist/render/lib/document/blocks/commerce/FilterBlock/render.js +1 -0
- package/dist/render/lib/document/blocks/commerce/FilterChipsBlock/meta.d.ts +8 -0
- package/dist/render/lib/document/blocks/commerce/FilterChipsBlock/meta.js +1 -0
- package/dist/render/lib/document/blocks/commerce/FilterChipsBlock/render.d.ts +2 -0
- package/dist/render/lib/document/blocks/commerce/FilterChipsBlock/render.js +1 -0
- package/dist/render/lib/document/blocks/commerce/GalleryB/meta.js +1 -1
- package/dist/render/lib/document/blocks/commerce/GalleryItem/render.js +1 -1
- package/dist/render/lib/document/blocks/commerce/ProductBuyButton/meta.d.ts +2 -0
- package/dist/render/lib/document/blocks/commerce/ProductBuyButton/meta.js +1 -0
- package/dist/render/lib/document/blocks/commerce/ProductBuyButton/render.d.ts +2 -0
- package/dist/render/lib/document/blocks/commerce/ProductBuyButton/render.js +1 -0
- package/dist/render/lib/document/blocks/commerce/ProductGrid/meta.js +1 -1
- package/dist/render/lib/document/blocks/commerce/ProductGrid/render.js +1 -1
- package/dist/render/lib/document/blocks/commerce/ProductHero/meta.js +1 -1
- package/dist/render/lib/document/blocks/commerce/ProductName/render.js +1 -1
- package/dist/render/lib/document/blocks/commerce/ProductPicture/render.js +1 -1
- package/dist/render/lib/document/blocks/commerce/metas.d.ts +3 -0
- package/dist/render/lib/document/blocks/commerce/metas.js +1 -1
- package/dist/render/lib/document/blocks/commerce/renders.d.ts +3 -0
- package/dist/render/lib/document/blocks/commerce/renders.js +1 -1
- package/dist/render/lib/document/card-templates.d.ts +1 -0
- package/dist/render/lib/document/card-templates.js +1 -1
- package/dist/render/lib/document/document-nodes.d.ts +24 -0
- package/dist/render/lib/document/document-nodes.js +1 -0
- package/dist/render/lib/document/lazy-draws.js +1 -1
- package/dist/render/lib/document/render-config.js +1 -1
- package/dist/render/lib/document/storefront-root.js +1 -1
- package/dist/render/lib/links/link-rules.js +1 -1
- package/dist/render/lib/sections/bundle-to-grid.d.ts +8 -0
- package/dist/render/lib/sections/bundle-to-grid.js +1 -0
- package/dist/render/lib/sections/catalog-text-size.d.ts +2 -0
- package/dist/render/lib/sections/catalog-text-size.js +1 -1
- package/dist/render/lib/sections/filter-option-rows.d.ts +37 -0
- package/dist/render/lib/sections/filter-option-rows.js +1 -0
- package/dist/render/lib/sections/gallery-toolbar.d.ts +27 -0
- package/dist/render/lib/sections/gallery-toolbar.js +1 -0
- package/dist/render/lib/sections/grid-no-hole.d.ts +3 -0
- package/dist/render/lib/sections/grid-no-hole.js +1 -1
- package/dist/render/lib/sections/product-grid-pages.d.ts +42 -0
- package/dist/render/lib/sections/product-grid-pages.js +1 -0
- package/dist/render/lib/sections/shopper-filters.d.ts +45 -0
- package/dist/render/lib/sections/shopper-filters.js +1 -0
- package/dist/render/lib/wheels/plp-filters.d.ts +6 -3
- package/dist/render/lib/wheels/plp-filters.js +1 -1
- package/dist/render/lib/wheels/plp-hydrate.d.ts +5 -3
- package/dist/render/lib/wheels/plp-hydrate.js +1 -1
- package/dist/render/lib/wheels/selected-ranges.d.ts +16 -0
- package/dist/render/lib/wheels/selected-ranges.js +1 -0
- package/dist/render/lib/wheels/set-mode.d.ts +10 -0
- package/dist/render/lib/wheels/set-mode.js +1 -1
- package/dist/render/lib/wheels/shopper-first-paint.d.ts +28 -0
- package/dist/render/lib/wheels/shopper-first-paint.js +1 -0
- package/dist/render/lib/wheels/shopper-scope.d.ts +11 -0
- package/dist/render/lib/wheels/shopper-scope.js +1 -0
- package/dist/words.d.ts +46 -6
- package/dist/words.js +6 -6
- package/package.json +4 -4
- package/dist/chunks/chunk-QLR6IVWJ.js +0 -369
- package/dist/chunks/chunk-SYK5QPNV.js +0 -1
- package/dist/chunks/chunk-XZ46W3NV.js +0 -1
- package/dist/render/components/pdp-dynamic/DynamicBundleOffer.d.ts +0 -13
- package/dist/render/components/pdp-dynamic/DynamicBundleOffer.js +0 -1
- /package/dist/chunks/{chunk-QLR6IVWJ.js.LEGAL.txt → chunk-WRDUOJZO.js.LEGAL.txt} +0 -0
- /package/dist/chunks/{chunk-DLWIDJS5.js → chunk-ZA3ULZOA.js} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useEffect, type ComponentType, type ReactNode } from "react";
|
|
2
|
+
import { type SelectedRanges } from "efficient-web-builder/render/lib/content/box-show-for";
|
|
3
|
+
import type { PlpItem } from "../../lib/catalog/plp-item.js";
|
|
4
|
+
import { type PlpFilterState, type PlpSortKey } from "../../lib/wheels/plp-filters.js";
|
|
5
|
+
import { type ShopperAddressMark as AddressMark } from "../../lib/wheels/selected-ranges.js";
|
|
6
|
+
import { type GallerySortKey, type GalleryTile, type GalleryToolbarState } from "../../lib/sections/gallery-toolbar.js";
|
|
7
|
+
export declare const useIsoLayoutEffect: typeof useEffect;
|
|
8
|
+
type Patch = Partial<PlpFilterState> | ((f: PlpFilterState) => PlpFilterState);
|
|
9
|
+
export interface GridShown {
|
|
10
|
+
total: number;
|
|
11
|
+
range: {
|
|
12
|
+
from: number;
|
|
13
|
+
to: number;
|
|
14
|
+
} | null;
|
|
15
|
+
}
|
|
16
|
+
export interface ChipParts {
|
|
17
|
+
count: boolean;
|
|
18
|
+
sort: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function ShopperScopeProvider({ children, address: stamped, editing, }: {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
address?: SelectedRanges | null;
|
|
23
|
+
editing?: boolean;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
25
|
+
export declare function ShopperAddressMark({ mark, children }: {
|
|
26
|
+
mark: AddressMark | null;
|
|
27
|
+
children?: ReactNode;
|
|
28
|
+
}): import("react").JSX.Element;
|
|
29
|
+
export declare function withShopperAddressMark<P extends Record<string, unknown>>(Draw: ComponentType<P>): (props: P) => ReactNode;
|
|
30
|
+
export interface ShopperScope {
|
|
31
|
+
key: string;
|
|
32
|
+
live: boolean;
|
|
33
|
+
state: PlpFilterState;
|
|
34
|
+
update: (patch: Patch) => void;
|
|
35
|
+
clear: () => void;
|
|
36
|
+
rows: readonly PlpItem[];
|
|
37
|
+
total: number;
|
|
38
|
+
grids: number;
|
|
39
|
+
countInChips: boolean;
|
|
40
|
+
sortInChips: boolean;
|
|
41
|
+
range: {
|
|
42
|
+
from: number;
|
|
43
|
+
to: number;
|
|
44
|
+
} | null;
|
|
45
|
+
}
|
|
46
|
+
export declare function useShopperFilter({ filtersBelow, openingSort, }: {
|
|
47
|
+
filtersBelow: boolean;
|
|
48
|
+
openingSort: PlpSortKey;
|
|
49
|
+
}): {
|
|
50
|
+
ref: (el: Element | null) => void;
|
|
51
|
+
scope: ShopperScope;
|
|
52
|
+
};
|
|
53
|
+
export declare function useShopperMember(role: "chips" | "grid", rows?: readonly PlpItem[] | null, parts?: ChipParts): {
|
|
54
|
+
ref: (el: Element | null) => void;
|
|
55
|
+
scope: ShopperScope | null;
|
|
56
|
+
reportShown: (shown: GridShown | null) => void;
|
|
57
|
+
gallery: GalleryToolbarScope | null;
|
|
58
|
+
};
|
|
59
|
+
export interface GalleryToolbarScope {
|
|
60
|
+
tags: readonly string[];
|
|
61
|
+
tag: string | null;
|
|
62
|
+
sort: GallerySortKey;
|
|
63
|
+
shown: number;
|
|
64
|
+
pick: (tag: string | null) => void;
|
|
65
|
+
setSort: (sort: GallerySortKey) => void;
|
|
66
|
+
clear: () => void;
|
|
67
|
+
}
|
|
68
|
+
export declare function useShopperGallery(tiles: readonly GalleryTile[]): {
|
|
69
|
+
ref: (el: Element | null) => void;
|
|
70
|
+
toolbar: GalleryToolbarState | null;
|
|
71
|
+
};
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";import{jsx as M}from"react/jsx-runtime";import{createContext as U,useCallback as k,useContext as R,useEffect as A,useId as ct,useLayoutEffect as it,useMemo as b,useRef as V,useState as I}from"react";import{useBoxId as ut}from"efficient-web-builder/render/components/InBoxContext";import{SelectedRangesProvider as ft}from"efficient-web-builder/render/lib/content/box-show-for";import{EMPTY_PLP_FILTERS as x,plpFiltersToParams as j}from"../../lib/wheels/plp-filters.js";import{VEHICLE_PARAM as pt}from"../../lib/wheels/plp-vehicle-params.js";import{readSelectedRanges as dt,shopperAddressMarkOf as wt}from"../../lib/wheels/selected-ranges.js";import{resolveGalleryFollows as gt,resolveShopperScopes as ht}from"../../lib/wheels/shopper-scope.js";import{clampGalleryTag as St,EMPTY_GALLERY_TOOLBAR as Y,galleryShownIds as mt,galleryTags as Pt}from"../../lib/sections/gallery-toolbar.js";import{filtersFromQuery as _t,watchLocation as kt}from"../wheels-plp/usePlpFiltersInUrl.js";const vt=typeof window<"u",E=vt?it:A,L=U(null),xt={assign:new Map,states:{},rows:{},shown:{},chipParts:{},galleryFollow:new Map,tiles:{},galleryStates:{}};function W(o,r){if(o.size!==r.size)return!1;for(const[u,s]of o)if(r.get(u)!==s)return!1;return!0}function X(o,r){return typeof r=="function"?r(o):{...o,...r}}function Ct(o,r){return j(o).toString()===j(r).toString()}function zt({children:o,address:r=null,editing:u=!1}){const s=V(new Map),[l,f]=I(xt),[p,d]=I(0),w=!u&&r?JSON.stringify(r):"",c=b(()=>w?r:null,[w]),[g,P]=I(null),_=k((t,n,e)=>{if(s.current.set(t.key,t),t.role==="filter"){const a=n??x;f(i=>i.states[t.key]?i:{...i,states:{...i.states,[t.key]:a}}),e&&P(i=>i??{key:t.key,opening:a.sort})}d(a=>a+1)},[]),S=k(t=>{P(n=>n?.key===t?null:n),s.current.delete(t),f(n=>{if(!(t in n.states)&&!(t in n.rows)&&!(t in n.shown)&&!(t in n.chipParts)&&!(t in n.tiles)&&!(t in n.galleryStates))return n;const{[t]:e,...a}=n.states,{[t]:i,...m}=n.rows,{[t]:C,...ot}=n.shown,{[t]:It,...st}=n.chipParts,{[t]:Tt,...lt}=n.tiles,{[t]:yt,...at}=n.galleryStates;return{...n,states:a,rows:m,shown:ot,chipParts:st,tiles:lt,galleryStates:at}}),d(n=>n+1)},[]);A(()=>{if(p===0)return;const t=[...s.current.values()],n=ht(t),e=gt(t);f(a=>{const i=W(a.assign,n),m=W(a.galleryFollow,e);return i&&m?a:{...a,assign:i?a.assign:n,galleryFollow:m?a.galleryFollow:e}})},[p]);const v=k((t,n)=>{f(e=>{const a=e.states[t];return a?{...e,states:{...e.states,[t]:X(a,n)}}:e})},[]),T=k((t,n)=>{f(e=>{if(n===null){if(!(t in e.rows))return e;const{[t]:a,...i}=e.rows;return{...e,rows:i}}return e.rows[t]===n?e:{...e,rows:{...e.rows,[t]:n}}})},[]),y=k((t,n)=>{f(e=>{if(n===null){if(!(t in e.shown))return e;const{[t]:m,...C}=e.shown;return{...e,shown:C}}const a=e.shown[t];return a&&a.total===n.total&&a.range?.from===n.range?.from&&a.range?.to===n.range?.to?e:{...e,shown:{...e.shown,[t]:n}}})},[]),D=k((t,n)=>{f(e=>{const a=e.chipParts[t],i=n.count||n.sort;if(!i&&!a||a&&a.count===n.count&&a.sort===n.sort)return e;const{[t]:m,...C}=e.chipParts;return{...e,chipParts:i?{...C,[t]:n}:C}})},[]),H=k((t,n)=>{f(e=>{if(n===null){if(!(t in e.tiles))return e;const{[t]:a,...i}=e.tiles;return{...e,tiles:i}}return e.tiles[t]===n?e:{...e,tiles:{...e.tiles,[t]:n}}})},[]),q=k((t,n)=>{f(e=>({...e,galleryStates:{...e.galleryStates,[t]:{...e.galleryStates[t]??Y,...n}}}))},[]),[G,nt]=I(null),h=g?.key??null,B=g?.opening??x.sort;A(()=>{if(!c||typeof window>"u")return;const t=()=>{const n=window.location.search,e=dt(n,c.known);if(nt(i=>i&&i.writer===h&&i.ranges.join(`
|
|
2
|
+
`)===e.join(`
|
|
3
|
+
`)?i:{ranges:e,writer:h}),!h)return;const a={..._t(n,B),collections:[...e]};f(i=>{const m=i.states[h];return!m||Ct(m,a)?i:{...i,states:{...i.states,[h]:{...m,...a}}}})};return t(),kt(t)},[c,h,B]);const F=h?l.states[h]:void 0;A(()=>{if(!c||!h||!F||G?.writer!==h||typeof window>"u")return;const t=j(F),n=new URLSearchParams(window.location.search);for(const i of Object.values(pt))for(const m of n.getAll(i))t.append(i,m);const e=t.toString(),a=e?`?${e}`:"";a!==window.location.search&&window.history.replaceState(null,"",`${window.location.pathname}${a}`)},[c,h,F,G]);const O=c?.known,J=F?.collections,Q=G?.ranges,et=b(()=>!c||!O?null:{selected:(J??Q??c.selected).filter(n=>O.includes(n)),known:O},[c,O,J,Q]),rt=b(()=>({snap:l,address:c,writer:h,register:_,unregister:S,update:v,reportRows:T,reportShown:y,reportChipParts:D,reportTiles:H,updateGallery:q}),[l,c,h,_,S,v,T,y,D,H,q]);return M(L.Provider,{value:rt,children:M(ft,{value:et,children:o})})}const N=U(null);function Mt({mark:o,children:r}){return M(N.Provider,{value:o,children:r})}function Dt(o){return function(u){return M(Mt,{mark:wt(u),children:M(o,{...u})})}}function Z(o,r){return{...x,sort:r,collections:[...o.selected]}}function $(o,r){if(!r)return null;const u=o.snap.states[r];if(!u)return null;const s=[];let l=0,f=0,p=!1,d=!1,w=null;for(const[c,g]of o.snap.assign){if(g!==r||c===r)continue;const P=o.snap.chipParts[c];P?.count&&(p=!0),P?.sort&&(d=!0);const _=o.snap.rows[c];if(!_)continue;f+=1,s.push(..._);const S=o.snap.shown[c];l+=S?.total??0,w=S?.range??null}return f!==1&&(w=null),{key:r,live:!0,state:u,update:c=>o.update(r,c),clear:()=>o.update(r,c=>({...x,sort:c.sort})),rows:s,total:l,grids:f,countInChips:p,sortInChips:d,range:w}}const K={count:!1,sort:!1};function z(o,r,u,s,l){const f=ct(),p=ut(),d=V(null),w=k(P=>{d.current=P},[]),c=o?.register,g=o?.unregister;return E(()=>{if(!(!c||!g))return c({key:f,role:r,boxId:p,node:d.current,filtersBelow:u},s,l),()=>g(f)},[c,g,f,r,p,u,l]),{key:f,ref:w}}function Ht({filtersBelow:o,openingSort:r}){const u=R(L),s=R(N),l=u?.address??null,f=!!s?.writes&&l!==null,p=f?Z(l,r):{...x,sort:r},{key:d,ref:w}=z(u,"filter",o,p,f),[c,g]=I(p),_=(u?$(u,d):null)??{key:d,live:!1,state:c,update:S=>g(v=>X(v,S)),clear:()=>g(S=>({...x,sort:S.sort})),rows:[],total:0,grids:0,countInChips:!1,sortInChips:!1,range:null};return{ref:w,scope:_}}function qt(o,r=null,u=K){const s=R(L),{key:l,ref:f}=z(s,o,!1),p=s?.reportRows,d=s?.reportShown;E(()=>{if(!(!p||o!=="grid"))return p(l,r),()=>p(l,null)},[p,l,o,r]);const w=k(y=>d?.(l,y),[d,l]);A(()=>()=>d?.(l,null),[d,l]);const c=s?.reportChipParts,{count:g,sort:P}=u;E(()=>{if(!(!c||o!=="chips"))return c(l,{count:g,sort:P}),()=>c(l,K)},[c,l,o,g,P]);const _=s?.snap.assign.get(l),S=R(N);let v=s?$(s,_):null;!v&&_===void 0&&s?.address&&S&&(v=(s.writer?$(s,s.writer):null)??At(Z(s.address,S.sort)));const T=s&&o==="chips"&&!v?Rt(s,s.snap.galleryFollow.get(l)):null;return{ref:f,scope:v,reportShown:w,gallery:T}}function Rt(o,r){if(!r)return null;const u=o.snap.tiles[r]??[],s=o.snap.galleryStates[r]??Y;return{tags:Pt(u),tag:St(s.tag,u),sort:s.sort,shown:mt(u,s).length,pick:l=>o.updateGallery(r,{tag:l}),setSort:l=>o.updateGallery(r,{sort:l}),clear:()=>o.updateGallery(r,{tag:null})}}function Bt(o){const r=R(L),{key:u,ref:s}=z(r,"gallery",!1),l=r?.reportTiles;E(()=>{if(l)return l(u,o),()=>l(u,null)},[l,u,o]);let f=!1;if(r)for(const[d,w]of r.snap.galleryFollow)w===u&&!r.snap.assign.get(d)&&(f=!0);const p=r&&f?r.snap.galleryStates[u]??Y:null;return{ref:s,toolbar:p}}const tt=()=>{};function At(o){return{key:"",live:!1,state:o,update:tt,clear:tt,rows:[],total:0,grids:0,countInChips:!1,sortInChips:!1,range:null}}export{Mt as ShopperAddressMark,zt as ShopperScopeProvider,E as useIsoLayoutEffect,Ht as useShopperFilter,Bt as useShopperGallery,qt as useShopperMember,Dt as withShopperAddressMark};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as r,jsxs as c}from"react/jsx-runtime";import i from"../ThemedSelect.js";import{CATALOG_TEXT_SIZE as n}from"../../lib/sections/catalog-text-size.js";const m={toolbar:"cursor-pointer border border-line bg-transparent px-2 py-2 font-mono text-[12px] normal-case tracking-normal text-fg",line:`border-b border-line bg-transparent pb-2 font-mono ${n.labelLarge} uppercase tracking-[0.2em] text-fg`,box:`border border-line bg-transparent px-4 py-3 font-mono ${n.labelLarge} uppercase tracking-[0.2em] text-fg`};function b({value:o,keys:l,labels:s,onChange:p,look:t="toolbar"}){const a=r(i,{"aria-label":"Sort results",align:"end",value:o,onChange:e=>p(e.target.value),className:m[t],children:l.map(e=>r("option",{value:e,children:s[e]},e))});return t!=="toolbar"?a:c("label",{className:"flex items-center gap-2 font-mono text-[11px] uppercase tracking-[0.16em] text-fg-dim",children:[r("span",{className:"whitespace-nowrap",children:"Sort by"}),a]})}export{b as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as
|
|
1
|
+
"use client";import{jsx as e,jsxs as $}from"react/jsx-runtime";import G from"../SectionBand.js";import{useScopeClass as Z}from"../../lib/use-scope-class.js";import{useEffect as q,useState as J}from"react";import{cardHoverOf as Q}from"efficient-web-builder/format/lib/animation/hover";const Y=Q({},"ProductGrid");import ee from"../CompatibleTyres.js";import{cardRowsGrid as re,GridBundleCards as te,GridCardProvider as oe,GridCards as ne,gridIndexCss as se}from"../GridCardTemplate.js";import{productGridColumnsClass as le}from"../../lib/sections/product-grid-columns.js";import{containerGapProps as B}from"efficient-web-builder/format/lib/content/container-gap";import{cardImageShapeTokens as D}from"efficient-web-builder/format/lib/content/card-image-shape";import{NO_FIELD_ANSWERS as ie}from"../../lib/content/field-usage.js";import{gridClassImageSizes as de}from"../../lib/sections/card-image-sizes.js";import{fillRowCss as ae}from"../../lib/sections/fill-row.js";import ce from"efficient-web-builder/render/components/SectionHeader";import pe from"../ViewMoreLink.js";import{useSiteMenuLinks as me}from"../catalog/SiteMenuLinks.js";import{renderGold as O,renderHeadline as ue}from"efficient-web-builder/render/components/goldPhrases";import fe from"./KindGate.js";import{loadProductCatalog as he}from"../useProductCatalog.js";import{PLP_KINDS as be}from"../../lib/catalog/plp-item.js";import{relatedCardCount as we,relatedViewMore as ye}from"../../lib/catalog/related-cards.js";import{answersWithProducts as M,DEFAULT_RELATIONSHIP as ge,relationshipApplies as W,relationshipByKey as xe}from"../../lib/catalog/relationships.js";import{useCurrentProduct as Ee}from"../../lib/document/current-product.js";import{PLACEHOLDER_RELATED as j}from"../../lib/wheels/placeholder-wheel.js";import{say as P}from"efficient-web-builder/format/lib/editor-words";const K={label:"text-[length:var(--size-label,13px)]"},ke=be;function ve(o){return e(fe,{kinds:ke,type:"RelatedProducts",editing:o.editing,children:e(Pe,{...o})})}function Pe({num:o,title:r,description:i,columns:d=3,cardCount:C,relationship:N=ge,footnote:w,footnoteLinkText:y,footnoteLinkHref:S,editing:n=!1,omitHead:a=!1,hover:R,ownerId:c="",template:m,cardImage:l,outline:g,indexBadge:u,columnsPhone:x,columnsTablet:E,gap:k,gapPhone:_}){const L={columns:d,columnsPhone:x,columnsTablet:E,gap:k,gapPhone:_,hover:R,ownerId:c,template:m,editing:n},s=Ee(),F=me(),v=we(C),t=xe(N),T=t?M(t):!1,[U,H]=J([]);if(q(()=>{if(s||!n||!T)return;let p=!1;return he().then(b=>{const X=b.length>0?b:j;p||H(X)}).catch(()=>{p||H(j)}),()=>{p=!0}},[s,n,T]),!t)return null;const f=a?null:e(ce,{num:o?O(o):void 0,title:ue(r||t.heading,!1),description:i?O(i):void 0,accent:!0});if(!M(t)){if(s&&!W(t,s.product.kind))return n?e(z,{relationship:t,cardImage:l}):null;const p=s?t.resolve(s.product,s.relatedWheels):null,b=p?.kind==="bundle"?p.bundles.slice(0,v):[];return b.length===0?n?e(V,{header:f,omitHead:a,cardImage:l,words:P("Bundles containing this product appear here on a product page.")}):null:e(I,{header:f,cards:{bundles:b},...L})}const A=ye(t,F);if(!s)return n?e(I,{header:f,cards:{wheels:U.slice(0,v)},viewMore:A,...L}):null;if(!W(t,s.product.kind))return n?e(z,{relationship:t,cardImage:l}):null;const h=t.resolve(s.product,s.relatedWheels);return h.kind==="tyre"?e(ee,{omitHead:a,columns:d,cardImage:l,outline:g,indexBadge:u,num:o,title:r||t.heading,description:i,tyres:[...h.tyres].slice(0,v),footnote:w,footnoteLinkText:y,footnoteLinkHref:S,viewMore:A,editing:n}):h.kind!=="alloy-wheel"?null:h.wheels.length===0?n?e(V,{header:f,omitHead:a,cardImage:l,words:P("Related products appear here on a product page.")}):null:e(I,{header:f,cards:{wheels:[...h.wheels].slice(0,v)},viewMore:A,...L})}function z({relationship:o,cardImage:r}){return e(G,{className:"border-b border-line py-14 max-view-desktop:py-10",style:D(r),children:e("p",{className:`font-mono ${K.label} uppercase tracking-[0.18em] text-fg-dim`,children:P("“{relationship}” does not apply to this product. It is hidden on the live page.",{relationship:P(o.label)})})})}const Ce="border-b border-line py-[120px] max-view-desktop:py-20",Ne="border-b border-line pt-0 pb-[120px] max-view-desktop:pt-0 max-view-desktop:pb-20";function V({header:o,omitHead:r,cardImage:i,words:d}){return $(G,{className:r?Ne:Ce,style:D(i),children:[o,e("p",{className:`border-t border-line py-6 font-mono ${K.label} uppercase tracking-[0.18em] text-fg-dim`,children:d})]})}function I({header:o,cards:r,viewMore:i,columns:d,columnsPhone:C,columnsTablet:N,gap:w,gapPhone:y,hover:S,ownerId:n,template:a,editing:R}){const c=Z("rp"),m="wheels"in r?r.wheels.length:r.bundles.length;if(m===0)return null;const l=le(d,C,N),g="bundles"in r,u=g?B("ProductGrid",w,"both",y):re(B("ProductGrid",w,"both",y)),x=se(c),E=ae(c,l,{cards:m}),k=_=>e("div",{className:g?`${c} mt-10 grid${u.className} ${l}`:`${c} grid${u.className} bg-[var(--catalog-grid-bg)] ${l}`,style:u.style,children:_});return $(G,{className:"border-b border-line py-[120px] max-view-desktop:py-20",children:[x&&e("style",{children:x}),E&&e("style",{children:E}),o,e(oe,{value:{ownerId:n,Template:a,hover:S??Y,imageSizes:de(l,m),fieldUsage:ie,reserveEyebrow:!1,editing:R},children:"wheels"in r?e(ne,{wheels:r.wheels,children:k}):e(te,{bundles:r.bundles,children:k})}),i?e("div",{className:"mt-10 flex",children:e(pe,{href:i.href,label:i.label})}):null]})}export{Pe as RelatedProductsBody,ve as default,ke as supportedKinds};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as r,jsxs as
|
|
1
|
+
"use client";import{jsx as r,jsxs as a}from"react/jsx-runtime";import{useCurrency as c}from"../CurrencyContext.js";import{formatPrice as f}from"../../lib/commerce.js";import{plpActiveChips as m}from"../../lib/wheels/plp-filters.js";function p({filters:t,onToggle:l,onPriceMax:s,onInStockOnly:i,onPickType:o}){const{currency:u}=c(),n=m(t,u,f);return n.length===0?null:r("ul",{className:"flex list-none flex-wrap items-center gap-2",children:n.map(e=>r("li",{children:a("button",{type:"button",onClick:()=>{if(e.key==="price")return s(null);if(e.key==="inStock")return i(!1);if(e.key==="kind")return o(null);if(!(e.key==="priceMin"||e.key==="lugs"))return l(e.key,e.value)},className:`flex cursor-pointer items-center gap-2 px-2 py-1 font-mono text-[10px] uppercase tracking-[0.14em] text-bg hover:bg-fg ${e.key==="inStock"?"bg-green":"bg-accent"}`,children:[e.label,r("span",{"aria-hidden":"true",children:"✕"}),r("span",{className:"sr-only",children:"Remove filter"})]})},`${e.key}:${e.value}`))})}export{p as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as o,jsxs as l}from"react/jsx-runtime";import{plpPageSequence as
|
|
1
|
+
"use client";import{jsx as o,jsxs as l}from"react/jsx-runtime";import{CATALOG_TEXT_SIZE as d}from"../../lib/sections/catalog-text-size.js";import{plpPageSequence as m}from"../../lib/wheels/plp-filters.js";function b({textSize:a=d.pager,page:r,pageCount:t,onPage:n}){if(t<=1)return null;const c=m(t,r),s=`flex h-9 w-9 cursor-pointer items-center justify-center border border-line font-mono ${a} transition-colors hover:border-accent hover:text-accent disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-line disabled:hover:text-fg`;return l("div",{className:"mt-8 flex flex-wrap items-center justify-between gap-4 border-t border-line pt-4",children:[l("div",{className:"flex items-center gap-2",children:[o("button",{type:"button",onClick:()=>n(r-1),disabled:r<=1,"aria-label":"Previous page",className:s,children:"‹"}),c.map((e,i)=>e===null?o("span",{className:`px-1 font-mono ${a} text-fg-dim`,children:"…"},`gap-${i}`):o("button",{type:"button",onClick:()=>n(e),"aria-current":e===r?"page":void 0,className:[`h-9 min-w-9 cursor-pointer border px-2 font-mono ${a} tabular-nums transition-colors`,e===r?"border-accent bg-accent text-bg":"border-line hover:border-accent hover:text-accent"].join(" "),children:e},e)),o("button",{type:"button",onClick:()=>n(r+1),disabled:r>=t,"aria-label":"Next page",className:s,children:"›"})]}),l("label",{className:"flex items-center gap-2 font-mono text-[11px] uppercase tracking-[0.16em] text-fg-dim",children:["Jump to",o("select",{value:r,onChange:e=>n(Number(e.target.value)),className:"cursor-pointer border border-line bg-transparent px-2 py-2 font-mono text-[12px] text-fg",children:Array.from({length:t},(e,i)=>i+1).map(e=>l("option",{value:e,children:["Page ",e," of ",t]},e))})]})]})}export{b as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import C from"../catalog/ClearAllButton.js";import{useState as _}from"react";import{useCurrency as $}from"../CurrencyContext.js";import{useEnglish as z}from"../EnglishVariant.js";import{formatPrice as y}from"../../lib/commerce.js";import{hasActivePlpFilters as j,PLP_FACET_LABELS as T}from"../../lib/wheels/plp-filters.js";import E from"./PlpInStockToggle.js";import A from"./PlpTypePicker.js";import F from"./PlpTyreSizeBoxes.js";function L({facets:i,filters:t,typeOptions:m,sizeBoxes:p,sizeMatches:g,noun:s,priceBounds:n,inStockCount:x,onToggle:v,onPickType:k,onPickSize:N,onPriceMax:w,onInStockOnly:P,onClearAll:S}){const{currency:f}=$(),o=z(),[d,h]=_({});return r("aside",{className:"w-full flex-none lg:sticky lg:[--sf-plp-rail-gap:16px] lg:[--sf-plp-rail-top:calc(var(--sf-header-h,88px)+var(--sf-plp-rail-gap))] lg:top-[var(--sf-plp-rail-top)] lg:max-h-[calc(100svh-var(--sf-plp-rail-top)-var(--sf-plp-rail-gap))] lg:w-[268px] lg:overflow-y-auto lg:overscroll-contain lg:pr-2.5",children:[r("div",{className:"flex items-center justify-between pb-2",children:[e("h2",{className:"font-display text-[18px] font-medium uppercase tracking-[-0.01em]",children:"Filter"}),j(t)&&e(C,{onClick:S,size:"text-[11px]"})]}),m.length>0&&e("div",{className:"pb-1 pt-1",children:e(A,{options:m,noun:s.many,onPick:k})}),x!==null&&e("div",{className:"border-t border-line py-2",children:e(E,{checked:t.inStockOnly,count:x,noun:s.many,onChange:P})}),p&&e(b,{label:o(T.tyreSizes),open:!d.tyreSizes,onToggle:()=>h(a=>({...a,tyreSizes:!a.tyreSizes})),children:!d.tyreSizes&&e("div",{className:"pb-3",children:e(F,{boxes:p,composed:t.tyreSizes[0]??"",matches:g,noun:s.many,onPick:N})})}),i.map(a=>{if(a.options.length===0)return null;const c=!d[a.key];return e(b,{label:o(a.label),open:c,onToggle:()=>h(l=>({...l,[a.key]:!l[a.key]})),children:c&&e("ul",{className:"flex flex-col pb-3",children:a.options.map(l=>{const u=l.count===0&&!l.checked;return e("li",{children:r("label",{className:`flex items-center gap-2.5 py-1 text-[13px] ${u?"opacity-40":"cursor-pointer"}`,children:[e("input",{type:"checkbox",checked:l.checked,disabled:u,onChange:()=>v(a.key,l.value),"aria-label":`${o(a.label)}: ${l.label} (${l.count} ${s.many})`,className:"h-[16px] w-[16px] flex-none accent-[var(--accent)]"}),l.swatch&&e("span",{className:"inline-block h-[13px] w-[13px] flex-none rounded-full shadow-[inset_0_0_0_1px_var(--site-line)]",style:{background:l.swatch}}),e("span",{className:"flex-1 capitalize",children:l.label}),e("span",{className:"font-mono text-[11px] tabular-nums text-fg-dim",children:l.count})]})},l.value)})})},a.key)}),n&&r("div",{className:"border-t border-line py-3",children:[r("span",{className:"font-mono text-[11px] uppercase tracking-[0.2em]",children:["Price · per ",s.one]}),e("input",{type:"range",min:n.min,max:n.max,step:5,value:t.priceMax??n.max,onChange:a=>{const c=Number(a.target.value);w(c>=n.max?null:c)},className:"mt-2 w-full accent-[var(--accent)]","aria-label":`Maximum price per ${s.one}`}),r("div",{className:"mt-1.5 flex justify-between font-mono text-[11px] tabular-nums",children:[e("span",{className:"text-fg-dim",children:y(n.min,f)}),r("span",{children:["Up to ",y(t.priceMax??n.max,f)]})]})]})]})}function b({label:i,open:t,onToggle:m,children:p}){return r("div",{className:"border-t border-line",children:[r("button",{type:"button",onClick:m,"aria-expanded":t,"aria-label":`${t?"Collapse":"Expand"} ${i} filters`,className:"flex w-full cursor-pointer items-center justify-between py-3 text-left",children:[e("span",{className:"font-mono text-[11px] uppercase tracking-[0.2em]",children:i}),e("span",{"aria-hidden":"true",className:`font-mono text-[10px] text-fg-dim transition-transform ${t?"rotate-180":""}`,children:"▾"})]}),p]})}export{L as default};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Dispatch, type SetStateAction } from "react";
|
|
2
2
|
import type { VehicleSelection } from "../../lib/wheels/fitment-options.js";
|
|
3
3
|
import { type PlpFilterState, type PlpSortKey } from "../../lib/wheels/plp-filters.js";
|
|
4
|
+
export declare function watchLocation(onChange: () => void): () => void;
|
|
4
5
|
export interface PlpUrlFiltersArgs {
|
|
5
6
|
editing: boolean;
|
|
6
7
|
openingSort: PlpSortKey;
|
|
@@ -8,4 +9,5 @@ export interface PlpUrlFiltersArgs {
|
|
|
8
9
|
vehicleRestored: boolean;
|
|
9
10
|
requestQuery?: string;
|
|
10
11
|
}
|
|
12
|
+
export declare function filtersFromQuery(search: string, openingSort: PlpSortKey): PlpFilterState;
|
|
11
13
|
export declare function usePlpFiltersInUrl({ editing, openingSort, appliedVehicle, vehicleRestored, requestQuery, }: PlpUrlFiltersArgs): [PlpFilterState, Dispatch<SetStateAction<PlpFilterState>>];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useEffect as d,useState as l}from"react";import{EMPTY_PLP_FILTERS as E,plpFiltersFromParams as L,plpFiltersToParams as i}from"../../lib/wheels/plp-filters.js";import{appendVehicleParams as P}from"../../lib/wheels/plp-vehicle-params.js";const
|
|
1
|
+
"use client";import{useEffect as d,useState as l}from"react";import{EMPTY_PLP_FILTERS as E,plpFiltersFromParams as L,plpFiltersToParams as i}from"../../lib/wheels/plp-filters.js";import{appendVehicleParams as P}from"../../lib/wheels/plp-vehicle-params.js";const p="plp:locationchange";let m=!1;function S(t){if(typeof window>"u")return()=>{};if(!m){m=!0;for(const e of["pushState","replaceState"]){const n=window.history[e];window.history[e]=function(...a){n.apply(this,a),window.dispatchEvent(new Event(p))}}}return window.addEventListener("popstate",t),window.addEventListener(p,t),()=>{window.removeEventListener("popstate",t),window.removeEventListener(p,t)}}function y(t,e){const n=L(new URLSearchParams(t));return i(n).toString()===""?{...E,sort:e}:n}function T({editing:t,openingSort:e,appliedVehicle:n,vehicleRestored:s,requestQuery:a}){const[c,w]=l(()=>y(t?"":a??"",e)),[f,h]=l(!1);return d(()=>{if(t||typeof window>"u")return;const r=()=>{const o=y(window.location.search,e);w(u=>i(u).toString()===i(o).toString()?u:o)};return r(),h(!0),S(r)},[t,e]),d(()=>{if(t||!f||!s||typeof window>"u")return;const r=i(c);P(r,n);const o=r.toString();window.history.replaceState(null,"",`${window.location.pathname}${o?`?${o}`:""}`)},[t,f,s,c,n]),[c,w]}export{y as filtersFromQuery,T as usePlpFiltersInUrl,S as watchLocation};
|
|
@@ -2,6 +2,7 @@ import type { AdminFieldUsageRow } from "../links/link-rules.js";
|
|
|
2
2
|
import type { TyreFitVehicleQuery } from "../tyres/tyre-vehicle-fitment.js";
|
|
3
3
|
import type { SocialPlatform } from "efficient-web-builder/format/lib/content/social-links";
|
|
4
4
|
import type { SiteThemeRow, SiteThemeRowPatch } from "efficient-web-builder/format/lib/site-theme-row";
|
|
5
|
+
import type { VideoFrames } from "efficient-web-builder/format/lib/web-backend";
|
|
5
6
|
export declare const API_URL: string;
|
|
6
7
|
export declare class ApiError extends Error {
|
|
7
8
|
status: number;
|
|
@@ -430,6 +431,7 @@ export interface AdminStorefrontPage {
|
|
|
430
431
|
group?: string | null;
|
|
431
432
|
kind?: "normal" | "dynamic" | "lightbox" | "footer";
|
|
432
433
|
live_state?: "live" | "changed" | "never";
|
|
434
|
+
video_frames?: VideoFrames;
|
|
433
435
|
}
|
|
434
436
|
export interface AdminGeocodeAnswer {
|
|
435
437
|
status: "found" | "not_found" | "try_again";
|
|
@@ -741,6 +743,8 @@ export declare function createStorefrontAdmin(client?: AdminClient): {
|
|
|
741
743
|
getSiteLiveState: (siteId: string, token: string) => Promise<AdminSiteLiveState>;
|
|
742
744
|
getThemeSettings: (token: string, siteId?: string) => Promise<AdminThemeSettings>;
|
|
743
745
|
updateThemeSettings: (patch: AdminThemeSettingsPatch, token: string, siteId?: string) => Promise<AdminThemeSettings>;
|
|
746
|
+
getMyPreferences: (token: string) => Promise<Record<string, unknown>>;
|
|
747
|
+
updateMyPreferences: (patch: Record<string, unknown>, token: string) => Promise<unknown>;
|
|
744
748
|
getChatSettings: (token: string, siteId?: string) => Promise<AdminChatSettings>;
|
|
745
749
|
updateChatSettings: (patch: AdminChatSettingsPatch, token: string, siteId?: string) => Promise<AdminChatSettings>;
|
|
746
750
|
getSocialSettings: (token: string, siteId: string) => Promise<AdminSocialSettings>;
|
|
@@ -819,6 +823,8 @@ export declare const storefrontAdmin: {
|
|
|
819
823
|
getSiteLiveState: (siteId: string, token: string) => Promise<AdminSiteLiveState>;
|
|
820
824
|
getThemeSettings: (token: string, siteId?: string) => Promise<AdminThemeSettings>;
|
|
821
825
|
updateThemeSettings: (patch: AdminThemeSettingsPatch, token: string, siteId?: string) => Promise<AdminThemeSettings>;
|
|
826
|
+
getMyPreferences: (token: string) => Promise<Record<string, unknown>>;
|
|
827
|
+
updateMyPreferences: (patch: Record<string, unknown>, token: string) => Promise<unknown>;
|
|
822
828
|
getChatSettings: (token: string, siteId?: string) => Promise<AdminChatSettings>;
|
|
823
829
|
updateChatSettings: (patch: AdminChatSettingsPatch, token: string, siteId?: string) => Promise<AdminChatSettings>;
|
|
824
830
|
getSocialSettings: (token: string, siteId: string) => Promise<AdminSocialSettings>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PREVIEW_TOKEN_HEADER as at,SITE_HOST_HEADER as st,SITE_SLUG_HEADER as nt}from"../site-headers.js";import{PRODUCT_API_BASE as ot,PRODUCT_BACKEND_URL as D}from"./origins.js";import{backendHopHeaders as it,clientIpFromForwardedFor as ct,FORWARDED_FOR_HEADER as dt,hopCachingOf as ut}from"../forwarded-for.js";import lt from"efficient-web-builder/format/lib/document/media-manifest.json";import{auth as P}from"../auth.js";import{efficientClientOpen as pt}from"efficient-easel/screen/lib/session";import{listableWheelSummaries as U}from"../wheels/listable-wheels.js";import{dropRenderlessFinishes as x}from"../wheels/renderable-finishes.js";const yt=process.env.NEXT_PUBLIC_API_URL??"http://localhost:8000";class m extends Error{status;data;constructor(e,s,o){super(s),this.status=e,this.data=o}}const I="Unable to reach the server. This could be a problem with your internet connection, or the server may be undergoing maintenance or an upgrade. Please try again shortly.",ht=new Set([502,503,504]),N=0,ft="This editor runs on its host's own backend, which does not serve this request.",gt=5e3,wt=15e3,mt=()=>typeof window>"u"?gt:wt;function H(t){const e=(t.method??"GET").toUpperCase();if(!(t.body!=null||e!=="GET"&&e!=="HEAD")&&!(t.audience!=null&&t.audience!=="shop")&&typeof AbortSignal?.timeout=="function")return AbortSignal.timeout(mt())}const F=t=>t instanceof Error&&t.name==="TimeoutError",M=(t,e)=>ht.has(t)?I:e,St=["admin","venue"];let B="admin";function ie(t){B=St.includes(t)?t:"admin"}function Pt(){return B}const Ot=/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{1,8})*$/;let q=null;function ce(t){q=t&&Ot.test(t)?t:null}function bt(){return q}function At(t){if(typeof window>"u"||!t.startsWith("/api/v1/"))return t;const e=K();return!e||/[?&]site=/.test(t)?t:E(t,`site=${encodeURIComponent(e)}`)}async function i(t,e={}){const{token:s,baseUrl:o,headers:l,audience:p,...w}=e;if(typeof window<"u"&&!pt())throw new m(N,ft,null);if(typeof window>"u"&&o===void 0)throw new Error(`apiFetch(${JSON.stringify(t)}) ran on the server without an explicit baseUrl. The API_URL default it would inherit is browser-only (the prod image bakes NEXT_PUBLIC_API_URL="" for same-origin use, which a Node fetch cannot resolve). Pass a base explicitly: \`await backendOpts()\` (or baseUrl: PRODUCT_FETCH_BASE) for product reads, or the server-only PRODUCT_BACKEND_URL env for other backend surfaces.`);const r=typeof FormData<"u"&&w.body instanceof FormData;let a;try{a=await fetch(`${o??yt}${At(t)}`,{...w,headers:{...r?{}:{"Content-Type":"application/json"},...s?{Authorization:`Bearer ${s}`}:{},...p===null?{}:{"X-Portal-Audience":p??"shop"},...l},signal:w.signal??H({...w,audience:p})})}catch(y){throw y instanceof TypeError||F(y)?new m(N,I,null):y}let n;try{n=await a.text()}catch(y){throw F(y)?new m(N,I,null):y}let c=null;if(n)try{c=JSON.parse(n)}catch{throw new m(a.status,a.ok?"Expected JSON but received a non-JSON response":M(a.status,a.statusText),n)}if(!a.ok){const y=(c&&typeof c=="object"&&"detail"in c&&typeof c.detail=="string"?c.detail:null)??M(a.status,a.statusText);throw new m(a.status,y,c)}return c}let b=null;async function G(){return b||(b=Tt().finally(()=>{b=null}),b)}async function Tt(){const t=P.takeLegacyRefresh(),e=await Rt.refresh(t??void 0);return P.setTokens(e.access),e.access}async function W(){return P.getAccess()??G()}async function h(t,e={}){let s;try{s=await W()}catch{throw P.clear(),new m(401,"Not signed in",null)}try{return await i(t,{...e,token:s})}catch(o){if(!(o instanceof m)||o.status!==401)throw o;try{const l=await G();return await i(t,{...e,token:l})}catch{throw P.clear(),o}}}async function j(t,e={}){if(P.getAccess())try{return{data:await h(t,e),asShopper:!0}}catch(s){if(!(s instanceof m)||s.status!==401)throw s}return{data:await i(t,e),asShopper:!1}}async function z(){const t=await h("/api/auth/me/");if(t.portal!=="shop")throw P.clear(),new m(403,"This session is not valid for this shop.",null);return t}const Rt={login:(t,e)=>i("/api/auth/login/",{method:"POST",body:JSON.stringify({email:t,password:e,portal:"shop"}),credentials:"include"}),refresh:t=>i("/api/auth/refresh/",{method:"POST",body:JSON.stringify(t?{refresh:t,portal:"shop"}:{portal:"shop"}),credentials:"include"}),logout:async()=>{P.clear();try{await i("/api/auth/logout/",{method:"POST",body:JSON.stringify({portal:"shop"}),credentials:"include"})}catch{}},restoreSession:async()=>{const t=await W();return await z(),t},me:z,updateMe:t=>h("/api/auth/me/",{method:"PATCH",body:JSON.stringify(t)}),changePassword:(t,e)=>h("/api/auth/me/",{method:"PATCH",body:JSON.stringify({password:e,old_password:t})}),changeEmail:(t,e)=>h("/api/shop-portal/change-email/",{method:"POST",body:JSON.stringify({new_email:t,current_password:e})}),myProfile:()=>h("/api/shop-portal/profile/"),updateMyProfile:t=>h("/api/shop-portal/profile/",{method:"PATCH",body:JSON.stringify(t)}),myAddresses:()=>h("/api/shop-portal/delivery-locations/"),createAddress:t=>h("/api/shop-portal/delivery-locations/",{method:"POST",body:JSON.stringify(t)}),updateAddress:(t,e)=>h(`/api/shop-portal/delivery-locations/${t}/`,{method:"PATCH",body:JSON.stringify(e)}),deleteAddress:t=>h(`/api/shop-portal/delivery-locations/${t}/`,{method:"DELETE"}),passwordResetRequest:t=>i("/api/auth/password-reset/",{method:"POST",body:JSON.stringify({email:t})}),passwordResetConfirm:(t,e,s)=>i("/api/auth/password-reset/confirm/",{method:"POST",body:JSON.stringify({uid:t,token:e,new_password:s})}),brands:()=>h("/api/products/brands/"),myOrders:()=>h("/api/shop-portal/orders/").then(t=>t.results),myOrder:t=>h(`/api/shop-portal/orders/${t}/`),cancelOrder:t=>h(`/api/shop-portal/orders/${t}/cancel/`,{method:"POST"}),myReturns:t=>h(`/api/shop-portal/returns/${t?`?order=${encodeURIComponent(t)}`:""}`).then(e=>e.results),createReturn:t=>h("/api/shop-portal/returns/",{method:"POST",body:JSON.stringify(t)}),withdrawReturn:t=>h(`/api/shop-portal/returns/${t}/cancel/`,{method:"POST"}),uploadReturnPhoto:(t,e)=>{const s=new FormData;return s.append("claim_item",t),s.append("file",e),s.append("media_type",e.type.startsWith("video/")?"video":"image"),h("/api/shop-portal/return-media/",{method:"POST",body:s})}};import{media as Et,absolutizeApiUrl as v}from"efficient-web-builder/render/lib/media";import{analyzeLogoSvg as Ct,isSvgUrl as $t}from"efficient-web-builder/format/lib/logo/reverse-svg";import{getEditorSiteId as _t}from"efficient-web-builder/render/lib/editor-site";import{shopRouteBase as Ut,webRuntimeSiteSlug as K}from"efficient-web-builder/format/lib/web-runtime";function g(t){if(typeof t=="string")return t.startsWith("/media/")?Et(t):t;if(Array.isArray(t))return t.map(g);if(t&&typeof t=="object"){const e={};for(const[s,o]of Object.entries(t))e[s]=s==="captions"&&o&&typeof o=="object"&&!Array.isArray(o)?Object.fromEntries(Object.entries(o).map(([l,p])=>[g(l),p])):g(o);return e}return t}import{PRODUCT_API_BASE as Pe}from"./origins.js";const V=typeof window>"u"&&D!=="",It=V?D:ot,Nt=Ut,O=()=>({baseUrl:Nt(),audience:null});function d(t,e){const s=e?`?process=${encodeURIComponent(e)}`:"";return`/api/v1${t}${s}`}const X=100,Z=50;function k(t,e,s){const o=new URLSearchParams;for(const[l,p]of Object.entries(e))p!=null&&p!==""&&o.set(l,String(p));return o.set("pageSize",String(X)),s&&o.set("cursor",s),`/api/v1${t}?${o.toString()}`}function vt(t,e){return k("/wheels",{process:t},e)}const Y=X;function kt(t,e){return k("/wheels",{slug:t.join(",")},e)}function Lt(t,e,s){return k("/products",{kind:t.join(","),make:e?.make,model:e?.model,year:e?.year,modification:e?.modification},s)}function Jt(t){if(!t)return null;try{return new URL(t,"http://cursor.invalid").searchParams.get("cursor")}catch{return null}}async function L(t,e,s=()=>!1){const o=[];let l=null;try{for(let p=0;p<Z;p++){const w=await i(await e(l),await u());if(o.push(...w.results),l=Jt(w.next),!l)break}l&&console.warn(`[${t}] stopped at ${Z} pages (${o.length} rows); catalog may be truncated`)}catch(p){if(s(p))throw p;console.warn(`[${t}] product API unavailable, returning []`,p)}return o}const Q=t=>t instanceof m&&t.status===400;function Dt(t){return t.flatMap(e=>e.kind==="alloy-wheel"?U([e]):[e])}async function tt(){return(await xt()).host}async function xt(){try{const{headers:t}=await import("next/headers"),e=await t(),s=p=>p?.split(",")[0]?.split(":")[0]?.trim().toLowerCase()||null,o=s(e.get(st)??e.get("x-forwarded-host")??e.get("host")),l=s(e.get("host"));return{host:o,matchesRequestHost:o!==null&&o===l}}catch{return{host:null,matchesRequestHost:!1}}}async function Ht(){try{const{headers:t}=await import("next/headers");return ct((await t()).get(dt))}catch{return null}}async function Ft(){try{const{headers:t}=await import("next/headers");return(await t()).get(nt)||null}catch{return null}}async function Mt(){const t=await Ft();if(t)return`site=${encodeURIComponent(t)}`;const e=await tt();return e?`host=${encodeURIComponent(e)}`:""}async function f(t){if(typeof window<"u"){const e=K();return e?E(t,`site=${encodeURIComponent(e)}`):t}return E(t,await Mt())}function E(t,e){return e?`${t}${t.includes("?")?"&":"?"}${e}`:t}const Bt="preview";async function qt(){if(typeof window<"u")return null;try{const{headers:t}=await import("next/headers");return(await t()).get(at)}catch{return null}}async function Gt(){try{const{headers:t}=await import("next/headers");return(await t()).get("user-agent")}catch{return null}}async function J(t,e){const s=await qt();if(s===null)return[await f(t),await u(e)];const o=E(await f(t),`${Bt}=${encodeURIComponent(s)}`),{next:l,cache:p,...w}=e??{},r=await u({...w,cache:"no-store"}),a=await Gt();return a&&(r.headers={...r.headers,"user-agent":a}),[o,r]}async function Wt(t){if(!V)return;const[e,s]=await Promise.all([tt(),Ht()]),o=it(e,s,t);return Object.keys(o).length>0?o:void 0}async function u(t){const e=await Wt(ut(t)),s={baseUrl:It,...t};return e&&(s.headers={...e,...t?.headers}),s}const A=typeof window>"u";function T(t,e){const s=new URLSearchParams;for(const[l,p]of Object.entries(e))p!==void 0&&p!==""&&s.set(l,String(p));const o=s.toString();return`/api/v1/fitment${t}${o?`?${o}`:""}`}const ye={listMakes:async t=>{if(A){const{fitmentData:s}=await import("./fitment-data.js");return s.makes(t)}return(await i(T("/makes",{region:t}),O())).results},listModels:async(t,e)=>{if(A){const{fitmentData:o}=await import("./fitment-data.js");return o.models(t,e)}return(await i(T("/models",{make:t,region:e}),O())).results},listYears:async(t,e,s)=>{if(A){const{fitmentData:l}=await import("./fitment-data.js");return l.years(t,e,s)}return(await i(T("/years",{make:t,model:e,region:s}),O())).results},listModifications:async(t,e,s,o)=>{if(A){const{fitmentData:p}=await import("./fitment-data.js");return p.modifications(t,e,s,o)}return(await i(T("/modifications",{make:t,model:e,year:s,region:o}),O())).results},getStockFitment:async(t,e,s,o,l)=>{if(A){const{fitmentData:p}=await import("./fitment-data.js");return p.stockFitment(t,e,s,o,l)}return i(T("/stock-fitment",{make:t,model:e,year:s,modification:o,region:l}),O())}},he={listWheels:async(t,e={})=>{const s=await L("products.listWheels",async o=>await f(vt(t,o)),e.throwOnFailure?()=>!0:void 0);return U(g(s))},listWheelsBySlug:async(t,e={})=>{const s=[...new Set(t.map(r=>r.trim()).filter(Boolean))];if(s.length===0)return[];const o=[];for(let r=0;r<s.length;r+=Y)o.push(s.slice(r,r+Y));const l=await Promise.all(o.map(r=>L("products.listWheelsBySlug",async a=>await f(kt(r,a)),e.throwOnFailure?()=>!0:Q))),p=new Set(s),w=l.flat().filter(r=>p.has(r.slug));return U(g(w))},listCatalog:async(t,e)=>{if(t.length===0)throw new Error("products.listCatalog() needs at least one kind. An empty list would omit `kind`, which the contract reads as `alloy-wheel` — so the call would silently return the wheel catalog instead of nothing.");const s=await L("products.listCatalog",async o=>await f(Lt(t,e,o)),Q);return Dt(g(s))},getWheel:async t=>x(g(await i(await f(d(`/wheels/${t}`)),await u()))),getTyre:async t=>g(await i(await f(d(`/tyres/${t}`)),await u())),listBundles:async(t={})=>{try{return await i(await f(d("/bundles")),await u())}catch(e){if(t.throwOnFailure)throw e;return[]}},getBundle:async t=>i(await f(d(`/bundles/${t}`)),await u()),listGalleryBuilds:async(t={})=>{const{process:e=null,wheelSlug:s=null}=t;if(typeof window>"u"){const{listGalleryBuilds:o}=await import("./gallery-builds-data.js");return g(o(e,s))}try{const o=new URLSearchParams;e&&o.set("process",e),s&&o.set("wheelSlug",s);const l=o.toString(),p=await i(`/api/v1/gallery-builds${l?`?${l}`:""}`,O());return g(p.results)}catch(o){return console.warn("[products.listGalleryBuilds] product API unavailable, returning []",o),[]}},getSite:async()=>i(await f(d("/site")),await u()),getSiteBySlug:async t=>i(`${d("/site")}?${new URLSearchParams({site:t})}`,typeof window>"u"?await u():void 0),listPages:async()=>g(await i(await f(d("/pages")),await u())),listPopups:async()=>i(await f(d("/popups")),await u()),listProductTemplates:async()=>{try{return await i(await f(d("/product-templates")),await u())}catch(t){return console.warn("[products.listProductTemplates] unavailable, returning []",t),[]}},listDynamicPages:async t=>{const e=t?`?recordType=${encodeURIComponent(t)}`:"";try{return await i(await f(`${d("/dynamic-pages")}${e}`),await u())}catch(s){if(s instanceof m&&s.status===404)return[];throw s}},getRecord:async(t,e)=>{try{return await i(await f(d(`/records/${encodeURIComponent(t)}/${encodeURIComponent(e)}`)),await u())}catch(s){if(s instanceof m&&s.status===404)return null;throw s}},listRecordKeys:async t=>{try{const e=await i(await f(d(`/records/${encodeURIComponent(t)}`)),await u({cache:"no-store"}));return Array.isArray(e?.keys)?e.keys.filter(s=>typeof s=="string"&&s!==""):[]}catch(e){if(e instanceof m&&e.status===404)return[];throw e}},listProductTypeChoices:async()=>{try{return await i(await f(d("/product-type-choices")),await u())}catch(t){return console.warn("[products.listProductTypeChoices] unavailable, returning []",t),[]}},listFieldUsage:async()=>{try{return await i(await f(d("/field-usage")),await u())}catch(t){return console.warn("[products.listFieldUsage] unavailable, returning []",t),[]}},getPage:async(t,e={})=>{const s=e.record?`?record=${encodeURIComponent(e.record)}`:"",[o,l]=await J(d(`/pages/${t}`)+s,e.revalidate!==void 0?{next:{revalidate:e.revalidate}}:void 0);return g(await i(o,l))},listBlogPosts:async(t={},{throwOnFailure:e=!1}={})=>{const s=t.category?`?category=${encodeURIComponent(t.category)}`:"";try{return(await i(d("/blog-posts")+s,await u())).map(l=>({...l,coverImage:v(l.coverImage)??""}))}catch(o){if(e)throw o;return console.warn("[products.listBlogPosts] blog API unavailable, returning []",o),[]}},getBlogPost:async t=>{const e=await i(d(`/blog-posts/${t}`),await u());return{...e,coverImage:v(e.coverImage)??""}},createOrder:async t=>i(d("/orders"),await u({method:"POST",body:JSON.stringify(t)})),createOrderAuthed:async t=>h(d("/orders"),await u({method:"POST",body:JSON.stringify(t)})),lookupOrder:async t=>i(d("/orders/lookup"),await u({method:"POST",body:JSON.stringify(t)})),createPaymentIntent:async t=>i(d("/payments/intent"),await u({method:"POST",body:JSON.stringify(t)})),releaseCheckout:async t=>i(d("/checkouts/release"),await u({method:"POST",body:JSON.stringify(t)})),createPaypalOrder:async t=>i(d("/payments/paypal/order"),await u({method:"POST",body:JSON.stringify(t)})),capturePaypalOrder:async t=>i(d("/payments/paypal/capture"),await u({method:"POST",body:JSON.stringify(t)})),createAfterpayCheckout:async t=>i(d("/payments/afterpay/checkout"),await u({method:"POST",body:JSON.stringify(t)})),captureAfterpayPayment:async t=>i(d("/payments/afterpay/capture"),await u({method:"POST",body:JSON.stringify(t)})),chargeSquare:async t=>i(d("/payments/square/charge"),await u({method:"POST",body:JSON.stringify(t)})),createGocardlessBillingRequest:async t=>i(d("/payments/gocardless/billing-request"),await u({method:"POST",body:JSON.stringify(t)})),completeGocardlessPayment:async t=>i(d("/payments/gocardless/complete"),await u({method:"POST",body:JSON.stringify(t)})),createZipCheckout:async t=>i(d("/payments/zip/checkout"),await u({method:"POST",body:JSON.stringify(t)})),captureZipPayment:async t=>i(d("/payments/zip/capture"),await u({method:"POST",body:JSON.stringify(t)})),createKlarnaCheckout:async t=>i(d("/payments/klarna/checkout"),await u({method:"POST",body:JSON.stringify(t)})),captureKlarnaPayment:async t=>i(d("/payments/klarna/capture"),await u({method:"POST",body:JSON.stringify(t)})),createStockAlert:async t=>i(d("/stock-alerts"),await u({method:"POST",body:JSON.stringify(t)})),createPreOrderIntent:async t=>i(d("/pre-order-intents"),await u({method:"POST",body:JSON.stringify(t)})),createNewsletterSubscription:async t=>i(d("/newsletter-subscriptions"),await u({method:"POST",body:JSON.stringify(t)})),unsubscribeNewsletter:async t=>i(d("/newsletter-unsubscribe"),await u({method:"POST",body:JSON.stringify(t)})),captureCart:async t=>i(d("/carts"),await u({method:"POST",body:JSON.stringify(t)})),restoreCart:async t=>i(d("/carts/restore"),await u({method:"POST",body:JSON.stringify(t)})),unsubscribeCartReminders:async t=>i(d("/carts/unsubscribe"),await u({method:"POST",body:JSON.stringify(t)})),listReviews:async(t={})=>{const e=new URLSearchParams;t.limit&&e.set("limit",String(t.limit)),t.designCode&&e.set("designCode",t.designCode);const s=d("/reviews"),o=e.toString();try{return await i(await f(o?`${s}?${o}`:s),await u())}catch(l){return console.warn("[products.listReviews] product API unavailable, returning []",l),[]}},submitReview:async t=>i(d("/reviews"),await u({method:"POST",body:JSON.stringify(t)})),getForm:async t=>i(d(`/forms/${encodeURIComponent(t)}`),await u()),submitForm:async(t,e)=>i(d(`/forms/${encodeURIComponent(t)}/submissions`),await u({method:"POST",body:JSON.stringify(e)})),listShippingMethods:async()=>{try{return await i(d("/shipping-methods"),await u())}catch(t){return console.warn("[products.listShippingMethods] product API unavailable, returning []",t),[]}},listCountrySubdivisions:async t=>{try{return await i(d(`/countries/${encodeURIComponent(t)}/subdivisions`),await u())}catch(e){return console.warn("[products.listCountrySubdivisions] unavailable, returning []",e),[]}},quoteCart:async t=>{const e=d("/cart/quote"),s=await u({method:"POST",body:JSON.stringify(t)});return t.couponCode?(await j(e,s)).data:i(e,s)},validateCoupon:async t=>{const{data:e,asShopper:s}=await j(d("/coupons/validate"),await u({method:"POST",body:JSON.stringify(t)}));return{...e,askedAsShopper:s}},getHeaderSettings:async()=>{const t=H({method:"GET"}),e=await i(...await J(d("/header-settings"),{signal:t})),s=v(e.logoUrl);let o=null,l=null;if(s&&$t(s)){const p=await Ct(s,t);p&&(o=p.reversed,l=p.inkIsDark)}return{...e,logoUrl:s,logoReversed:o,logoInkIsDark:l}},getThemeSettings:async()=>i(...await J(d("/theme-settings"))),getChatSettings:async()=>i(await f(d("/chat-settings")),await u())},fe={listServices:async()=>{try{return await i(d("/bookings/services"),await u())}catch(t){return console.warn("[bookings.listServices] API unavailable, returning []",t),{results:[],currency:"USD"}}},getAvailability:async(t,e)=>i(d(`/bookings/availability?service=${encodeURIComponent(t)}&date=${e}`),await u()),create:async t=>i(d("/bookings"),await u({method:"POST",body:JSON.stringify(t)})),get:async t=>i(d(`/bookings/manage/${encodeURIComponent(t)}`),await u()),cancel:async t=>i(d(`/bookings/manage/${encodeURIComponent(t)}/cancel`),await u({method:"POST"})),createPaymentIntent:async t=>i(d("/bookings/payments/intent"),await u({method:"POST",body:JSON.stringify({manageToken:t})}))};class jt extends Error{slug;count;constructor(e,s){super(`Slug "${e}" exists on ${s} websites; a site is required to pick one.`),this.slug=e,this.count=s,this.name="AmbiguousPageSlugError"}}const C=(t,e,s)=>{const o=new URLSearchParams({...e?{site:e}:{},...s?{draft:"1"}:{}}).toString();return`/api/storefront/${t}/${o?`?${o}`:""}`},$=t=>`/api/storefront/sites/${encodeURIComponent(t)}/`,zt=t=>`${$(t)}currencies/`,Kt="/api/storefront/media/ingest/";class Vt extends Error{constructor(){super("This editor is not connected to a website, so an upload has nowhere to go. Open the page from the website the file should belong to, then try again."),this.name="MediaUploadDestinationError"}}function Xt(){const t=_t();if(!t)throw new Vt;return`${Kt}?${new URLSearchParams({site:t})}`}const Zt="X-Puck-Media-Manifest",et=lt.contentHash,_={"X-Media-Manifest":et,[Zt]:et},ge=rt({});function rt(t){return(e,s={})=>{const o=bt(),l=t.headers||o?{...o?{"Accept-Language":o}:{},...t.headers,...s.headers}:void 0;return i(e,{...s,...t.baseUrl!==void 0?{baseUrl:t.baseUrl}:{},...l?{headers:l}:{},audience:t.audience??Pt()})}}function Yt(t={}){const e=rt(t),s=t.siteDrafts===!0,o=r=>C("header-settings",r,s),l=r=>C("theme-settings",r,s),p=r=>C("chat-settings",r,s),w=r=>C("social-settings",r,s);return{findPageBySlug:async(r,a,n)=>{const c=new URLSearchParams({slug:r});n&&c.set("site",n);const y=await e(`/api/storefront/pages/?${c.toString()}`,{token:a}),S=Array.isArray(y)?y:y.results??[];if(!n&&S.length>1)throw new jt(r,S.length);return S[0]??null},getPageById:(r,a)=>e(`/api/storefront/pages/${r}/`,{token:a}),saveLayout:(r,a,n,c,y)=>e(`/api/storefront/pages/${r}/`,{method:"PATCH",body:JSON.stringify({layout:a,expected_updated_at:c,...y?{client_id:y}:{}}),token:n}),duplicatePage:(r,a,n)=>e(`/api/storefront/pages/${r}/duplicate/`,{method:"POST",body:JSON.stringify({title:a.title,slug:a.slug}),token:n}),geocode:(r,a,n)=>e(`/api/storefront/geocode/?${new URLSearchParams(n?{q:r,country:n}:{q:r})}`,{token:a}),listBlockSources:r=>e("/api/storefront/block-sources/",{token:r}),listRecordTypes:r=>e("/api/storefront/record-types/",{token:r}),createPagePreviewLink:(r,a)=>e(`/api/storefront/pages/${r}/preview-link/`,{method:"POST",token:a}),claimPageEditLock:(r,a,n,c=!1)=>e(`/api/storefront/pages/${r}/edit-lock/`,{method:"POST",body:JSON.stringify({client_id:n,takeover:c}),token:a}),releasePageEditLock:(r,a)=>e(`/api/storefront/pages/${r}/edit-lock/`,{method:"DELETE",token:a}),createTemplate:(r,a,n)=>e("/api/storefront/page-templates/",{method:"POST",body:JSON.stringify({name:r,layout:a}),headers:_,token:n}),getTemplate:(r,a)=>e(`/api/storefront/page-templates/${r}/`,{token:a}),saveTemplateLayout:(r,a,n)=>e(`/api/storefront/page-templates/${r}/`,{method:"PATCH",body:JSON.stringify({layout:a}),headers:_,token:n}),listTemplatePages:async(r,a)=>{const n=await e(`/api/storefront/template-pages/?template=${encodeURIComponent(r)}`,{token:a});return Array.isArray(n)?n:n.results??[]},findTemplatePageBySlug:async(r,a,n)=>{const c=await e(`/api/storefront/template-pages/?template=${encodeURIComponent(r)}&slug=${encodeURIComponent(a)}`,{token:n});return(Array.isArray(c)?c:c.results??[])[0]??null},createTemplatePage:(r,a,n)=>e("/api/storefront/template-pages/",{method:"POST",body:JSON.stringify({template:r,...a}),headers:_,token:n}),saveTemplatePageLayout:(r,a,n)=>e(`/api/storefront/template-pages/${r}/`,{method:"PATCH",body:JSON.stringify({layout:a}),headers:_,token:n}),deleteTemplatePage:(r,a,n)=>e(`/api/storefront/template-pages/${r}/`,{method:"DELETE",token:a,...n?.keepalive?{keepalive:!0}:{}}),listPages:async(r,a)=>{const n=new URLSearchParams({no_page:"true"});a&&n.set("site",a);const c=await e(`/api/storefront/pages/?${n.toString()}`,{token:r});return Array.isArray(c)?c:c.results??[]},createPage:(r,a,n,c)=>e("/api/storefront/pages/",{method:"POST",body:JSON.stringify({title:r,slug:a,layout:n}),token:c}),deletePage:(r,a)=>e(`/api/storefront/pages/${r}/`,{method:"DELETE",token:a}),getHeaderSettings:(r,a)=>e(o(a),{token:r}),listMenus:async(r,a)=>{const n=new URLSearchParams({no_page:"true"});a&&n.set("site",a);const c=await e(`/api/storefront/menus/?${n}`,{token:r});return Array.isArray(c)?c:c.results??[]},listBlogPosts:async(r,a={})=>{const n=new URLSearchParams({no_page:"true"});a.visibleOnly&&n.set("is_visible","true"),a.siteId&&n.set("site",a.siteId);const c=await e(`/api/storefront/blog-posts/?${n.toString()}`,{token:r});return Array.isArray(c)?c:c.results??[]},listFieldUsage:async(r,a)=>{const n=await e(`/api/storefront/field-usage/?site=${encodeURIComponent(a)}`,{token:r});return Array.isArray(n?.entries)?n.entries:[]},listCategories:async(r,a={})=>{const n=new URLSearchParams({no_page:"true"});a.visibleOnly&&n.set("is_visible","true"),a.siteId&&n.set("site",a.siteId);const c=await e(`/api/storefront/categories/?${n.toString()}`,{token:r});return[...Array.isArray(c)?c:c.results??[]].sort((S,R)=>S.sort_order-R.sort_order||S.name.localeCompare(R.name))},listForms:async(r,a={})=>{const n=new URLSearchParams({no_page:"true"});a.siteId&&n.set("site",a.siteId);const c=await e(`/api/storefront/forms/?${n.toString()}`,{token:r});return[...Array.isArray(c)?c:c.results??[]].sort((S,R)=>S.title.localeCompare(R.title))},listWheelSummaries:async(r,a={})=>{const n=new URLSearchParams;a.siteId&&n.set("site",a.siteId);const c=n.toString(),y=await e(`/api/storefront/wheel-curations/summaries/${c?`?${c}`:""}`,{token:r});return g(y)},listProducts:async(r,a={})=>{const n=new URLSearchParams;a.kinds?.length&&n.set("kind",a.kinds.join(",")),a.siteId&&n.set("site",a.siteId);const c=n.toString(),y=await e(`/api/storefront/products/${c?`?${c}`:""}`,{token:r});return g(y)},getWheelDetail:async(r,a,n={})=>{const c=new URLSearchParams({slug:a});return n.siteId&&c.set("site",n.siteId),x(g(await e(`/api/storefront/wheel-curations/detail/?${c.toString()}`,{token:r})))},updateHeaderSettings:(r,a,n)=>e(o(n),{method:"PATCH",body:JSON.stringify(r),token:a}),getSite:(r,a)=>e($(r),{token:a}),listSites:async r=>{const a=await e("/api/storefront/sites/?no_page=true",{token:r});return Array.isArray(a)?a:a.results??[]},listSiteCurrencies:async(r,a)=>{const n=await e(zt(r),{token:a});return Array.isArray(n)?n:[]},publishSite:(r,a)=>e(`${$(r)}publish/`,{method:"POST",token:a}),getSiteLiveState:(r,a)=>e(`${$(r)}live-state/`,{token:a}),getThemeSettings:(r,a)=>e(l(a),{token:r}),updateThemeSettings:(r,a,n)=>e(l(n),{method:"PATCH",body:JSON.stringify(r),token:a}),getChatSettings:(r,a)=>e(p(a),{token:r}),updateChatSettings:(r,a,n)=>e(p(n),{method:"PATCH",body:JSON.stringify(r),token:a}),getSocialSettings:(r,a)=>e(w(a),{token:r}),updateSocialSettings:(r,a,n)=>e(w(n),{method:"PATCH",body:JSON.stringify(r),token:a}),uploadHeaderLogo:(r,a,n)=>{const c=new FormData;return c.append("logo",r),e(o(n),{method:"PATCH",body:c,token:a})},clearHeaderLogo:(r,a)=>e(o(a),{method:"PATCH",body:JSON.stringify({logo:null}),token:r}),setHeaderLogoFromAsset:(r,a,n)=>e(o(n),{method:"PATCH",body:JSON.stringify({logo_asset_id:r}),token:a}),uploadMedia:async(r,a)=>{const n=new FormData;return n.append("file",r),e(Xt(),{method:"POST",body:n,token:a})},listMedia:async(r,a)=>{const n=new URLSearchParams({no_page:"true"});a&&n.set("kind",a);const c=await e(`/api/storefront/media-assets/?${n.toString()}`,{token:r});return Array.isArray(c)?c:c.results??[]}}}const we=Yt({siteDrafts:!0});export{yt as API_URL,jt as AmbiguousPageSlugError,m as ApiError,wt as BROWSER_READ_TIMEOUT_MS,ft as EFFICIENT_CLIENT_CLOSED_MESSAGE,Vt as MediaUploadDestinationError,Bt as PREVIEW_PARAM,Pe as PRODUCT_API_BASE,gt as SERVER_READ_TIMEOUT_MS,I as SERVER_UNREACHABLE_MESSAGE,N as STATUS_NETWORK_ERROR,ge as adminFetch,Rt as api,i as apiFetch,E as appendSiteQuery,fe as bookings,Yt as createStorefrontAdmin,H as defaultRequestDeadline,Xt as editorMediaUploadPath,Pt as editorPortalAudience,bt as editorRequestLanguage,ye as fitment,he as products,mt as readDeadlineMs,Ht as resolveClientIp,g as resolveMediaUrls,qt as resolvePreviewToken,tt as resolveSiteHost,xt as resolveSiteHostSource,Ft as resolveSiteSlug,ce as setEditorLanguage,ie as setEditorPortalAudience,we as storefrontAdmin};
|
|
1
|
+
import{PREVIEW_TOKEN_HEADER as at,SITE_HOST_HEADER as st,SITE_SLUG_HEADER as nt}from"../site-headers.js";import{PRODUCT_API_BASE as ot,PRODUCT_BACKEND_URL as D}from"./origins.js";import{backendHopHeaders as it,clientIpFromForwardedFor as ct,FORWARDED_FOR_HEADER as dt,hopCachingOf as ut}from"../forwarded-for.js";import lt from"efficient-web-builder/format/lib/document/media-manifest.json";import{auth as P}from"../auth.js";import{efficientClientOpen as pt}from"efficient-easel/screen/lib/session";import{listableWheelSummaries as U}from"../wheels/listable-wheels.js";import{dropRenderlessFinishes as x}from"../wheels/renderable-finishes.js";const yt=process.env.NEXT_PUBLIC_API_URL??"http://localhost:8000";class m extends Error{status;data;constructor(e,s,o){super(s),this.status=e,this.data=o}}const N="Unable to reach the server. This could be a problem with your internet connection, or the server may be undergoing maintenance or an upgrade. Please try again shortly.",ht=new Set([502,503,504]),I=0,ft="This editor runs on its host's own backend, which does not serve this request.",gt=5e3,wt=15e3,mt=()=>typeof window>"u"?gt:wt;function H(t){const e=(t.method??"GET").toUpperCase();if(!(t.body!=null||e!=="GET"&&e!=="HEAD")&&!(t.audience!=null&&t.audience!=="shop")&&typeof AbortSignal?.timeout=="function")return AbortSignal.timeout(mt())}const F=t=>t instanceof Error&&t.name==="TimeoutError",M=(t,e)=>ht.has(t)?N:e,St=["admin","venue"];let B="admin";function ie(t){B=St.includes(t)?t:"admin"}function Pt(){return B}const Ot=/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{1,8})*$/;let q=null;function ce(t){q=t&&Ot.test(t)?t:null}function bt(){return q}function At(t){if(typeof window>"u"||!t.startsWith("/api/v1/"))return t;const e=K();return!e||/[?&]site=/.test(t)?t:E(t,`site=${encodeURIComponent(e)}`)}async function i(t,e={}){const{token:s,baseUrl:o,headers:l,audience:p,...w}=e;if(typeof window<"u"&&!pt())throw new m(I,ft,null);if(typeof window>"u"&&o===void 0)throw new Error(`apiFetch(${JSON.stringify(t)}) ran on the server without an explicit baseUrl. The API_URL default it would inherit is browser-only (the prod image bakes NEXT_PUBLIC_API_URL="" for same-origin use, which a Node fetch cannot resolve). Pass a base explicitly: \`await backendOpts()\` (or baseUrl: PRODUCT_FETCH_BASE) for product reads, or the server-only PRODUCT_BACKEND_URL env for other backend surfaces.`);const r=typeof FormData<"u"&&w.body instanceof FormData;let a;try{a=await fetch(`${o??yt}${At(t)}`,{...w,headers:{...r?{}:{"Content-Type":"application/json"},...s?{Authorization:`Bearer ${s}`}:{},...p===null?{}:{"X-Portal-Audience":p??"shop"},...l},signal:w.signal??H({...w,audience:p})})}catch(y){throw y instanceof TypeError||F(y)?new m(I,N,null):y}let n;try{n=await a.text()}catch(y){throw F(y)?new m(I,N,null):y}let c=null;if(n)try{c=JSON.parse(n)}catch{throw new m(a.status,a.ok?"Expected JSON but received a non-JSON response":M(a.status,a.statusText),n)}if(!a.ok){const y=(c&&typeof c=="object"&&"detail"in c&&typeof c.detail=="string"?c.detail:null)??M(a.status,a.statusText);throw new m(a.status,y,c)}return c}let b=null;async function G(){return b||(b=Tt().finally(()=>{b=null}),b)}async function Tt(){const t=P.takeLegacyRefresh(),e=await Rt.refresh(t??void 0);return P.setTokens(e.access),e.access}async function W(){return P.getAccess()??G()}async function h(t,e={}){let s;try{s=await W()}catch{throw P.clear(),new m(401,"Not signed in",null)}try{return await i(t,{...e,token:s})}catch(o){if(!(o instanceof m)||o.status!==401)throw o;try{const l=await G();return await i(t,{...e,token:l})}catch{throw P.clear(),o}}}async function j(t,e={}){if(P.getAccess())try{return{data:await h(t,e),asShopper:!0}}catch(s){if(!(s instanceof m)||s.status!==401)throw s}return{data:await i(t,e),asShopper:!1}}async function z(){const t=await h("/api/auth/me/");if(t.portal!=="shop")throw P.clear(),new m(403,"This session is not valid for this shop.",null);return t}const Rt={login:(t,e)=>i("/api/auth/login/",{method:"POST",body:JSON.stringify({email:t,password:e,portal:"shop"}),credentials:"include"}),refresh:t=>i("/api/auth/refresh/",{method:"POST",body:JSON.stringify(t?{refresh:t,portal:"shop"}:{portal:"shop"}),credentials:"include"}),logout:async()=>{P.clear();try{await i("/api/auth/logout/",{method:"POST",body:JSON.stringify({portal:"shop"}),credentials:"include"})}catch{}},restoreSession:async()=>{const t=await W();return await z(),t},me:z,updateMe:t=>h("/api/auth/me/",{method:"PATCH",body:JSON.stringify(t)}),changePassword:(t,e)=>h("/api/auth/me/",{method:"PATCH",body:JSON.stringify({password:e,old_password:t})}),changeEmail:(t,e)=>h("/api/shop-portal/change-email/",{method:"POST",body:JSON.stringify({new_email:t,current_password:e})}),myProfile:()=>h("/api/shop-portal/profile/"),updateMyProfile:t=>h("/api/shop-portal/profile/",{method:"PATCH",body:JSON.stringify(t)}),myAddresses:()=>h("/api/shop-portal/delivery-locations/"),createAddress:t=>h("/api/shop-portal/delivery-locations/",{method:"POST",body:JSON.stringify(t)}),updateAddress:(t,e)=>h(`/api/shop-portal/delivery-locations/${t}/`,{method:"PATCH",body:JSON.stringify(e)}),deleteAddress:t=>h(`/api/shop-portal/delivery-locations/${t}/`,{method:"DELETE"}),passwordResetRequest:t=>i("/api/auth/password-reset/",{method:"POST",body:JSON.stringify({email:t})}),passwordResetConfirm:(t,e,s)=>i("/api/auth/password-reset/confirm/",{method:"POST",body:JSON.stringify({uid:t,token:e,new_password:s})}),brands:()=>h("/api/products/brands/"),myOrders:()=>h("/api/shop-portal/orders/").then(t=>t.results),myOrder:t=>h(`/api/shop-portal/orders/${t}/`),cancelOrder:t=>h(`/api/shop-portal/orders/${t}/cancel/`,{method:"POST"}),myReturns:t=>h(`/api/shop-portal/returns/${t?`?order=${encodeURIComponent(t)}`:""}`).then(e=>e.results),createReturn:t=>h("/api/shop-portal/returns/",{method:"POST",body:JSON.stringify(t)}),withdrawReturn:t=>h(`/api/shop-portal/returns/${t}/cancel/`,{method:"POST"}),uploadReturnPhoto:(t,e)=>{const s=new FormData;return s.append("claim_item",t),s.append("file",e),s.append("media_type",e.type.startsWith("video/")?"video":"image"),h("/api/shop-portal/return-media/",{method:"POST",body:s})}};import{media as Et,absolutizeApiUrl as v}from"efficient-web-builder/render/lib/media";import{analyzeLogoSvg as Ct,isSvgUrl as $t}from"efficient-web-builder/format/lib/logo/reverse-svg";import{getEditorSiteId as _t}from"efficient-web-builder/render/lib/editor-site";import{shopRouteBase as Ut,webRuntimeSiteSlug as K}from"efficient-web-builder/format/lib/web-runtime";function g(t){if(typeof t=="string")return t.startsWith("/media/")?Et(t):t;if(Array.isArray(t))return t.map(g);if(t&&typeof t=="object"){const e={};for(const[s,o]of Object.entries(t))e[s]=s==="captions"&&o&&typeof o=="object"&&!Array.isArray(o)?Object.fromEntries(Object.entries(o).map(([l,p])=>[g(l),p])):g(o);return e}return t}import{PRODUCT_API_BASE as Pe}from"./origins.js";const V=typeof window>"u"&&D!=="",Nt=V?D:ot,It=Ut,O=()=>({baseUrl:It(),audience:null});function d(t,e){const s=e?`?process=${encodeURIComponent(e)}`:"";return`/api/v1${t}${s}`}const X=100,Z=50;function k(t,e,s){const o=new URLSearchParams;for(const[l,p]of Object.entries(e))p!=null&&p!==""&&o.set(l,String(p));return o.set("pageSize",String(X)),s&&o.set("cursor",s),`/api/v1${t}?${o.toString()}`}function vt(t,e){return k("/wheels",{process:t},e)}const Y=X;function kt(t,e){return k("/wheels",{slug:t.join(",")},e)}function Jt(t,e,s){return k("/products",{kind:t.join(","),make:e?.make,model:e?.model,year:e?.year,modification:e?.modification},s)}function Lt(t){if(!t)return null;try{return new URL(t,"http://cursor.invalid").searchParams.get("cursor")}catch{return null}}async function J(t,e,s=()=>!1){const o=[];let l=null;try{for(let p=0;p<Z;p++){const w=await i(await e(l),await u());if(o.push(...w.results),l=Lt(w.next),!l)break}l&&console.warn(`[${t}] stopped at ${Z} pages (${o.length} rows); catalog may be truncated`)}catch(p){if(s(p))throw p;console.warn(`[${t}] product API unavailable, returning []`,p)}return o}const Q=t=>t instanceof m&&t.status===400;function Dt(t){return t.flatMap(e=>e.kind==="alloy-wheel"?U([e]):[e])}async function tt(){return(await xt()).host}async function xt(){try{const{headers:t}=await import("next/headers"),e=await t(),s=p=>p?.split(",")[0]?.split(":")[0]?.trim().toLowerCase()||null,o=s(e.get(st)??e.get("x-forwarded-host")??e.get("host")),l=s(e.get("host"));return{host:o,matchesRequestHost:o!==null&&o===l}}catch{return{host:null,matchesRequestHost:!1}}}async function Ht(){try{const{headers:t}=await import("next/headers");return ct((await t()).get(dt))}catch{return null}}async function Ft(){try{const{headers:t}=await import("next/headers");return(await t()).get(nt)||null}catch{return null}}async function Mt(){const t=await Ft();if(t)return`site=${encodeURIComponent(t)}`;const e=await tt();return e?`host=${encodeURIComponent(e)}`:""}async function f(t){if(typeof window<"u"){const e=K();return e?E(t,`site=${encodeURIComponent(e)}`):t}return E(t,await Mt())}function E(t,e){return e?`${t}${t.includes("?")?"&":"?"}${e}`:t}const Bt="preview";async function qt(){if(typeof window<"u")return null;try{const{headers:t}=await import("next/headers");return(await t()).get(at)}catch{return null}}async function Gt(){try{const{headers:t}=await import("next/headers");return(await t()).get("user-agent")}catch{return null}}async function L(t,e){const s=await qt();if(s===null)return[await f(t),await u(e)];const o=E(await f(t),`${Bt}=${encodeURIComponent(s)}`),{next:l,cache:p,...w}=e??{},r=await u({...w,cache:"no-store"}),a=await Gt();return a&&(r.headers={...r.headers,"user-agent":a}),[o,r]}async function Wt(t){if(!V)return;const[e,s]=await Promise.all([tt(),Ht()]),o=it(e,s,t);return Object.keys(o).length>0?o:void 0}async function u(t){const e=await Wt(ut(t)),s={baseUrl:Nt,...t};return e&&(s.headers={...e,...t?.headers}),s}const A=typeof window>"u";function T(t,e){const s=new URLSearchParams;for(const[l,p]of Object.entries(e))p!==void 0&&p!==""&&s.set(l,String(p));const o=s.toString();return`/api/v1/fitment${t}${o?`?${o}`:""}`}const ye={listMakes:async t=>{if(A){const{fitmentData:s}=await import("./fitment-data.js");return s.makes(t)}return(await i(T("/makes",{region:t}),O())).results},listModels:async(t,e)=>{if(A){const{fitmentData:o}=await import("./fitment-data.js");return o.models(t,e)}return(await i(T("/models",{make:t,region:e}),O())).results},listYears:async(t,e,s)=>{if(A){const{fitmentData:l}=await import("./fitment-data.js");return l.years(t,e,s)}return(await i(T("/years",{make:t,model:e,region:s}),O())).results},listModifications:async(t,e,s,o)=>{if(A){const{fitmentData:p}=await import("./fitment-data.js");return p.modifications(t,e,s,o)}return(await i(T("/modifications",{make:t,model:e,year:s,region:o}),O())).results},getStockFitment:async(t,e,s,o,l)=>{if(A){const{fitmentData:p}=await import("./fitment-data.js");return p.stockFitment(t,e,s,o,l)}return i(T("/stock-fitment",{make:t,model:e,year:s,modification:o,region:l}),O())}},he={listWheels:async(t,e={})=>{const s=await J("products.listWheels",async o=>await f(vt(t,o)),e.throwOnFailure?()=>!0:void 0);return U(g(s))},listWheelsBySlug:async(t,e={})=>{const s=[...new Set(t.map(r=>r.trim()).filter(Boolean))];if(s.length===0)return[];const o=[];for(let r=0;r<s.length;r+=Y)o.push(s.slice(r,r+Y));const l=await Promise.all(o.map(r=>J("products.listWheelsBySlug",async a=>await f(kt(r,a)),e.throwOnFailure?()=>!0:Q))),p=new Set(s),w=l.flat().filter(r=>p.has(r.slug));return U(g(w))},listCatalog:async(t,e)=>{if(t.length===0)throw new Error("products.listCatalog() needs at least one kind. An empty list would omit `kind`, which the contract reads as `alloy-wheel` — so the call would silently return the wheel catalog instead of nothing.");const s=await J("products.listCatalog",async o=>await f(Jt(t,e,o)),Q);return Dt(g(s))},getWheel:async t=>x(g(await i(await f(d(`/wheels/${t}`)),await u()))),getTyre:async t=>g(await i(await f(d(`/tyres/${t}`)),await u())),listBundles:async(t={})=>{try{return await i(await f(d("/bundles")),await u())}catch(e){if(t.throwOnFailure)throw e;return[]}},getBundle:async t=>i(await f(d(`/bundles/${t}`)),await u()),listGalleryBuilds:async(t={})=>{const{process:e=null,wheelSlug:s=null}=t;if(typeof window>"u"){const{listGalleryBuilds:o}=await import("./gallery-builds-data.js");return g(o(e,s))}try{const o=new URLSearchParams;e&&o.set("process",e),s&&o.set("wheelSlug",s);const l=o.toString(),p=await i(`/api/v1/gallery-builds${l?`?${l}`:""}`,O());return g(p.results)}catch(o){return console.warn("[products.listGalleryBuilds] product API unavailable, returning []",o),[]}},getSite:async()=>i(await f(d("/site")),await u()),getSiteBySlug:async t=>i(`${d("/site")}?${new URLSearchParams({site:t})}`,typeof window>"u"?await u():void 0),listPages:async()=>g(await i(await f(d("/pages")),await u())),listPopups:async()=>i(await f(d("/popups")),await u()),listProductTemplates:async()=>{try{return await i(await f(d("/product-templates")),await u())}catch(t){return console.warn("[products.listProductTemplates] unavailable, returning []",t),[]}},listDynamicPages:async t=>{const e=t?`?recordType=${encodeURIComponent(t)}`:"";try{return await i(await f(`${d("/dynamic-pages")}${e}`),await u())}catch(s){if(s instanceof m&&s.status===404)return[];throw s}},getRecord:async(t,e)=>{try{return await i(await f(d(`/records/${encodeURIComponent(t)}/${encodeURIComponent(e)}`)),await u())}catch(s){if(s instanceof m&&s.status===404)return null;throw s}},listRecordKeys:async t=>{try{const e=await i(await f(d(`/records/${encodeURIComponent(t)}`)),await u({cache:"no-store"}));return Array.isArray(e?.keys)?e.keys.filter(s=>typeof s=="string"&&s!==""):[]}catch(e){if(e instanceof m&&e.status===404)return[];throw e}},listProductTypeChoices:async()=>{try{return await i(await f(d("/product-type-choices")),await u())}catch(t){return console.warn("[products.listProductTypeChoices] unavailable, returning []",t),[]}},listFieldUsage:async()=>{try{return await i(await f(d("/field-usage")),await u())}catch(t){return console.warn("[products.listFieldUsage] unavailable, returning []",t),[]}},getPage:async(t,e={})=>{const s=e.record?`?record=${encodeURIComponent(e.record)}`:"",[o,l]=await L(d(`/pages/${t}`)+s,e.revalidate!==void 0?{next:{revalidate:e.revalidate}}:void 0);return g(await i(o,l))},listBlogPosts:async(t={},{throwOnFailure:e=!1}={})=>{const s=t.category?`?category=${encodeURIComponent(t.category)}`:"";try{return(await i(d("/blog-posts")+s,await u())).map(l=>({...l,coverImage:v(l.coverImage)??""}))}catch(o){if(e)throw o;return console.warn("[products.listBlogPosts] blog API unavailable, returning []",o),[]}},getBlogPost:async t=>{const e=await i(d(`/blog-posts/${t}`),await u());return{...e,coverImage:v(e.coverImage)??""}},createOrder:async t=>i(d("/orders"),await u({method:"POST",body:JSON.stringify(t)})),createOrderAuthed:async t=>h(d("/orders"),await u({method:"POST",body:JSON.stringify(t)})),lookupOrder:async t=>i(d("/orders/lookup"),await u({method:"POST",body:JSON.stringify(t)})),createPaymentIntent:async t=>i(d("/payments/intent"),await u({method:"POST",body:JSON.stringify(t)})),releaseCheckout:async t=>i(d("/checkouts/release"),await u({method:"POST",body:JSON.stringify(t)})),createPaypalOrder:async t=>i(d("/payments/paypal/order"),await u({method:"POST",body:JSON.stringify(t)})),capturePaypalOrder:async t=>i(d("/payments/paypal/capture"),await u({method:"POST",body:JSON.stringify(t)})),createAfterpayCheckout:async t=>i(d("/payments/afterpay/checkout"),await u({method:"POST",body:JSON.stringify(t)})),captureAfterpayPayment:async t=>i(d("/payments/afterpay/capture"),await u({method:"POST",body:JSON.stringify(t)})),chargeSquare:async t=>i(d("/payments/square/charge"),await u({method:"POST",body:JSON.stringify(t)})),createGocardlessBillingRequest:async t=>i(d("/payments/gocardless/billing-request"),await u({method:"POST",body:JSON.stringify(t)})),completeGocardlessPayment:async t=>i(d("/payments/gocardless/complete"),await u({method:"POST",body:JSON.stringify(t)})),createZipCheckout:async t=>i(d("/payments/zip/checkout"),await u({method:"POST",body:JSON.stringify(t)})),captureZipPayment:async t=>i(d("/payments/zip/capture"),await u({method:"POST",body:JSON.stringify(t)})),createKlarnaCheckout:async t=>i(d("/payments/klarna/checkout"),await u({method:"POST",body:JSON.stringify(t)})),captureKlarnaPayment:async t=>i(d("/payments/klarna/capture"),await u({method:"POST",body:JSON.stringify(t)})),createStockAlert:async t=>i(d("/stock-alerts"),await u({method:"POST",body:JSON.stringify(t)})),createPreOrderIntent:async t=>i(d("/pre-order-intents"),await u({method:"POST",body:JSON.stringify(t)})),createNewsletterSubscription:async t=>i(d("/newsletter-subscriptions"),await u({method:"POST",body:JSON.stringify(t)})),unsubscribeNewsletter:async t=>i(d("/newsletter-unsubscribe"),await u({method:"POST",body:JSON.stringify(t)})),captureCart:async t=>i(d("/carts"),await u({method:"POST",body:JSON.stringify(t)})),restoreCart:async t=>i(d("/carts/restore"),await u({method:"POST",body:JSON.stringify(t)})),unsubscribeCartReminders:async t=>i(d("/carts/unsubscribe"),await u({method:"POST",body:JSON.stringify(t)})),listReviews:async(t={})=>{const e=new URLSearchParams;t.limit&&e.set("limit",String(t.limit)),t.designCode&&e.set("designCode",t.designCode);const s=d("/reviews"),o=e.toString();try{return await i(await f(o?`${s}?${o}`:s),await u())}catch(l){return console.warn("[products.listReviews] product API unavailable, returning []",l),[]}},submitReview:async t=>i(d("/reviews"),await u({method:"POST",body:JSON.stringify(t)})),getForm:async t=>i(d(`/forms/${encodeURIComponent(t)}`),await u()),submitForm:async(t,e)=>i(d(`/forms/${encodeURIComponent(t)}/submissions`),await u({method:"POST",body:JSON.stringify(e)})),listShippingMethods:async()=>{try{return await i(d("/shipping-methods"),await u())}catch(t){return console.warn("[products.listShippingMethods] product API unavailable, returning []",t),[]}},listCountrySubdivisions:async t=>{try{return await i(d(`/countries/${encodeURIComponent(t)}/subdivisions`),await u())}catch(e){return console.warn("[products.listCountrySubdivisions] unavailable, returning []",e),[]}},quoteCart:async t=>{const e=d("/cart/quote"),s=await u({method:"POST",body:JSON.stringify(t)});return t.couponCode?(await j(e,s)).data:i(e,s)},validateCoupon:async t=>{const{data:e,asShopper:s}=await j(d("/coupons/validate"),await u({method:"POST",body:JSON.stringify(t)}));return{...e,askedAsShopper:s}},getHeaderSettings:async()=>{const t=H({method:"GET"}),e=await i(...await L(d("/header-settings"),{signal:t})),s=v(e.logoUrl);let o=null,l=null;if(s&&$t(s)){const p=await Ct(s,t);p&&(o=p.reversed,l=p.inkIsDark)}return{...e,logoUrl:s,logoReversed:o,logoInkIsDark:l}},getThemeSettings:async()=>i(...await L(d("/theme-settings"))),getChatSettings:async()=>i(await f(d("/chat-settings")),await u())},fe={listServices:async()=>{try{return await i(d("/bookings/services"),await u())}catch(t){return console.warn("[bookings.listServices] API unavailable, returning []",t),{results:[],currency:"USD"}}},getAvailability:async(t,e)=>i(d(`/bookings/availability?service=${encodeURIComponent(t)}&date=${e}`),await u()),create:async t=>i(d("/bookings"),await u({method:"POST",body:JSON.stringify(t)})),get:async t=>i(d(`/bookings/manage/${encodeURIComponent(t)}`),await u()),cancel:async t=>i(d(`/bookings/manage/${encodeURIComponent(t)}/cancel`),await u({method:"POST"})),createPaymentIntent:async t=>i(d("/bookings/payments/intent"),await u({method:"POST",body:JSON.stringify({manageToken:t})}))};class jt extends Error{slug;count;constructor(e,s){super(`Slug "${e}" exists on ${s} websites; a site is required to pick one.`),this.slug=e,this.count=s,this.name="AmbiguousPageSlugError"}}const C=(t,e,s)=>{const o=new URLSearchParams({...e?{site:e}:{},...s?{draft:"1"}:{}}).toString();return`/api/storefront/${t}/${o?`?${o}`:""}`},$=t=>`/api/storefront/sites/${encodeURIComponent(t)}/`,zt=t=>`${$(t)}currencies/`,Kt="/api/storefront/media/ingest/";class Vt extends Error{constructor(){super("This editor is not connected to a website, so an upload has nowhere to go. Open the page from the website the file should belong to, then try again."),this.name="MediaUploadDestinationError"}}function Xt(){const t=_t();if(!t)throw new Vt;return`${Kt}?${new URLSearchParams({site:t})}`}const Zt="X-Puck-Media-Manifest",et=lt.contentHash,_={"X-Media-Manifest":et,[Zt]:et},ge=rt({});function rt(t){return(e,s={})=>{const o=bt(),l=t.headers||o?{...o?{"Accept-Language":o}:{},...t.headers,...s.headers}:void 0;return i(e,{...s,...t.baseUrl!==void 0?{baseUrl:t.baseUrl}:{},...l?{headers:l}:{},audience:t.audience??Pt()})}}function Yt(t={}){const e=rt(t),s=t.siteDrafts===!0,o=r=>C("header-settings",r,s),l=r=>C("theme-settings",r,s),p=r=>C("chat-settings",r,s),w=r=>C("social-settings",r,s);return{findPageBySlug:async(r,a,n)=>{const c=new URLSearchParams({slug:r});n&&c.set("site",n);const y=await e(`/api/storefront/pages/?${c.toString()}`,{token:a}),S=Array.isArray(y)?y:y.results??[];if(!n&&S.length>1)throw new jt(r,S.length);return S[0]??null},getPageById:(r,a)=>e(`/api/storefront/pages/${r}/`,{token:a}),saveLayout:(r,a,n,c,y)=>e(`/api/storefront/pages/${r}/`,{method:"PATCH",body:JSON.stringify({layout:a,expected_updated_at:c,...y?{client_id:y}:{}}),token:n}),duplicatePage:(r,a,n)=>e(`/api/storefront/pages/${r}/duplicate/`,{method:"POST",body:JSON.stringify({title:a.title,slug:a.slug}),token:n}),geocode:(r,a,n)=>e(`/api/storefront/geocode/?${new URLSearchParams(n?{q:r,country:n}:{q:r})}`,{token:a}),listBlockSources:r=>e("/api/storefront/block-sources/",{token:r}),listRecordTypes:r=>e("/api/storefront/record-types/",{token:r}),createPagePreviewLink:(r,a)=>e(`/api/storefront/pages/${r}/preview-link/`,{method:"POST",token:a}),claimPageEditLock:(r,a,n,c=!1)=>e(`/api/storefront/pages/${r}/edit-lock/`,{method:"POST",body:JSON.stringify({client_id:n,takeover:c}),token:a}),releasePageEditLock:(r,a)=>e(`/api/storefront/pages/${r}/edit-lock/`,{method:"DELETE",token:a}),createTemplate:(r,a,n)=>e("/api/storefront/page-templates/",{method:"POST",body:JSON.stringify({name:r,layout:a}),headers:_,token:n}),getTemplate:(r,a)=>e(`/api/storefront/page-templates/${r}/`,{token:a}),saveTemplateLayout:(r,a,n)=>e(`/api/storefront/page-templates/${r}/`,{method:"PATCH",body:JSON.stringify({layout:a}),headers:_,token:n}),listTemplatePages:async(r,a)=>{const n=await e(`/api/storefront/template-pages/?template=${encodeURIComponent(r)}`,{token:a});return Array.isArray(n)?n:n.results??[]},findTemplatePageBySlug:async(r,a,n)=>{const c=await e(`/api/storefront/template-pages/?template=${encodeURIComponent(r)}&slug=${encodeURIComponent(a)}`,{token:n});return(Array.isArray(c)?c:c.results??[])[0]??null},createTemplatePage:(r,a,n)=>e("/api/storefront/template-pages/",{method:"POST",body:JSON.stringify({template:r,...a}),headers:_,token:n}),saveTemplatePageLayout:(r,a,n)=>e(`/api/storefront/template-pages/${r}/`,{method:"PATCH",body:JSON.stringify({layout:a}),headers:_,token:n}),deleteTemplatePage:(r,a,n)=>e(`/api/storefront/template-pages/${r}/`,{method:"DELETE",token:a,...n?.keepalive?{keepalive:!0}:{}}),listPages:async(r,a)=>{const n=new URLSearchParams({no_page:"true"});a&&n.set("site",a);const c=await e(`/api/storefront/pages/?${n.toString()}`,{token:r});return Array.isArray(c)?c:c.results??[]},createPage:(r,a,n,c)=>e("/api/storefront/pages/",{method:"POST",body:JSON.stringify({title:r,slug:a,layout:n}),token:c}),deletePage:(r,a)=>e(`/api/storefront/pages/${r}/`,{method:"DELETE",token:a}),getHeaderSettings:(r,a)=>e(o(a),{token:r}),listMenus:async(r,a)=>{const n=new URLSearchParams({no_page:"true"});a&&n.set("site",a);const c=await e(`/api/storefront/menus/?${n}`,{token:r});return Array.isArray(c)?c:c.results??[]},listBlogPosts:async(r,a={})=>{const n=new URLSearchParams({no_page:"true"});a.visibleOnly&&n.set("is_visible","true"),a.siteId&&n.set("site",a.siteId);const c=await e(`/api/storefront/blog-posts/?${n.toString()}`,{token:r});return Array.isArray(c)?c:c.results??[]},listFieldUsage:async(r,a)=>{const n=await e(`/api/storefront/field-usage/?site=${encodeURIComponent(a)}`,{token:r});return Array.isArray(n?.entries)?n.entries:[]},listCategories:async(r,a={})=>{const n=new URLSearchParams({no_page:"true"});a.visibleOnly&&n.set("is_visible","true"),a.siteId&&n.set("site",a.siteId);const c=await e(`/api/storefront/categories/?${n.toString()}`,{token:r});return[...Array.isArray(c)?c:c.results??[]].sort((S,R)=>S.sort_order-R.sort_order||S.name.localeCompare(R.name))},listForms:async(r,a={})=>{const n=new URLSearchParams({no_page:"true"});a.siteId&&n.set("site",a.siteId);const c=await e(`/api/storefront/forms/?${n.toString()}`,{token:r});return[...Array.isArray(c)?c:c.results??[]].sort((S,R)=>S.title.localeCompare(R.title))},listWheelSummaries:async(r,a={})=>{const n=new URLSearchParams;a.siteId&&n.set("site",a.siteId);const c=n.toString(),y=await e(`/api/storefront/wheel-curations/summaries/${c?`?${c}`:""}`,{token:r});return g(y)},listProducts:async(r,a={})=>{const n=new URLSearchParams;a.kinds?.length&&n.set("kind",a.kinds.join(",")),a.siteId&&n.set("site",a.siteId);const c=n.toString(),y=await e(`/api/storefront/products/${c?`?${c}`:""}`,{token:r});return g(y)},getWheelDetail:async(r,a,n={})=>{const c=new URLSearchParams({slug:a});return n.siteId&&c.set("site",n.siteId),x(g(await e(`/api/storefront/wheel-curations/detail/?${c.toString()}`,{token:r})))},updateHeaderSettings:(r,a,n)=>e(o(n),{method:"PATCH",body:JSON.stringify(r),token:a}),getSite:(r,a)=>e($(r),{token:a}),listSites:async r=>{const a=await e("/api/storefront/sites/?no_page=true",{token:r});return Array.isArray(a)?a:a.results??[]},listSiteCurrencies:async(r,a)=>{const n=await e(zt(r),{token:a});return Array.isArray(n)?n:[]},publishSite:(r,a)=>e(`${$(r)}publish/`,{method:"POST",token:a}),getSiteLiveState:(r,a)=>e(`${$(r)}live-state/`,{token:a}),getThemeSettings:(r,a)=>e(l(a),{token:r}),updateThemeSettings:(r,a,n)=>e(l(n),{method:"PATCH",body:JSON.stringify(r),token:a}),getMyPreferences:async r=>(await e("/api/auth/me/",{token:r})).preferences??{},updateMyPreferences:(r,a)=>e("/api/auth/me/",{method:"PATCH",body:JSON.stringify({preferences:r}),token:a}),getChatSettings:(r,a)=>e(p(a),{token:r}),updateChatSettings:(r,a,n)=>e(p(n),{method:"PATCH",body:JSON.stringify(r),token:a}),getSocialSettings:(r,a)=>e(w(a),{token:r}),updateSocialSettings:(r,a,n)=>e(w(n),{method:"PATCH",body:JSON.stringify(r),token:a}),uploadHeaderLogo:(r,a,n)=>{const c=new FormData;return c.append("logo",r),e(o(n),{method:"PATCH",body:c,token:a})},clearHeaderLogo:(r,a)=>e(o(a),{method:"PATCH",body:JSON.stringify({logo:null}),token:r}),setHeaderLogoFromAsset:(r,a,n)=>e(o(n),{method:"PATCH",body:JSON.stringify({logo_asset_id:r}),token:a}),uploadMedia:async(r,a)=>{const n=new FormData;return n.append("file",r),e(Xt(),{method:"POST",body:n,token:a})},listMedia:async(r,a)=>{const n=new URLSearchParams({no_page:"true"});a&&n.set("kind",a);const c=await e(`/api/storefront/media-assets/?${n.toString()}`,{token:r});return Array.isArray(c)?c:c.results??[]}}}const we=Yt({siteDrafts:!0});export{yt as API_URL,jt as AmbiguousPageSlugError,m as ApiError,wt as BROWSER_READ_TIMEOUT_MS,ft as EFFICIENT_CLIENT_CLOSED_MESSAGE,Vt as MediaUploadDestinationError,Bt as PREVIEW_PARAM,Pe as PRODUCT_API_BASE,gt as SERVER_READ_TIMEOUT_MS,N as SERVER_UNREACHABLE_MESSAGE,I as STATUS_NETWORK_ERROR,ge as adminFetch,Rt as api,i as apiFetch,E as appendSiteQuery,fe as bookings,Yt as createStorefrontAdmin,H as defaultRequestDeadline,Xt as editorMediaUploadPath,Pt as editorPortalAudience,bt as editorRequestLanguage,ye as fitment,he as products,mt as readDeadlineMs,Ht as resolveClientIp,g as resolveMediaUrls,qt as resolvePreviewToken,tt as resolveSiteHost,xt as resolveSiteHostSource,Ft as resolveSiteSlug,ce as setEditorLanguage,ie as setEditorPortalAudience,we as storefrontAdmin};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SiteMenuLink } from "./listing-links.js";
|
|
2
2
|
import type { Relationship } from "./relationships.js";
|
|
3
|
+
import type { ProductKind } from "../api/index.js";
|
|
3
4
|
export declare const RELATED_CARDS_MIN = 2;
|
|
4
5
|
export declare const RELATED_CARDS_DEFAULT = 6;
|
|
5
6
|
export declare const RELATED_CARDS_MAX = 12;
|
|
@@ -9,4 +10,6 @@ export interface RelatedViewMore {
|
|
|
9
10
|
href: string;
|
|
10
11
|
label: string;
|
|
11
12
|
}
|
|
12
|
-
export declare function relatedViewMore(relationship: Relationship
|
|
13
|
+
export declare function relatedViewMore(relationship: Relationship & {
|
|
14
|
+
to: ProductKind;
|
|
15
|
+
}, menuLinks?: readonly SiteMenuLink[]): RelatedViewMore;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompatibleTyre, ProductKind, WheelSummary } from "../api/index.js";
|
|
1
|
+
import type { Bundle, CompatibleTyre, ProductKind, WheelSummary } from "../api/index.js";
|
|
2
2
|
import type { StoreProduct } from "./store-product.js";
|
|
3
3
|
export type RelatedCards = {
|
|
4
4
|
kind: "tyre";
|
|
@@ -6,12 +6,16 @@ export type RelatedCards = {
|
|
|
6
6
|
} | {
|
|
7
7
|
kind: "alloy-wheel";
|
|
8
8
|
wheels: readonly WheelSummary[];
|
|
9
|
+
} | {
|
|
10
|
+
kind: "bundle";
|
|
11
|
+
bundles: readonly Bundle[];
|
|
9
12
|
};
|
|
13
|
+
export type RelatedKind = ProductKind | "bundle";
|
|
10
14
|
export interface Relationship {
|
|
11
15
|
key: string;
|
|
12
16
|
label: string;
|
|
13
17
|
from: readonly ProductKind[];
|
|
14
|
-
to:
|
|
18
|
+
to: RelatedKind;
|
|
15
19
|
heading: string;
|
|
16
20
|
resolve(product: StoreProduct, relatedWheels: readonly WheelSummary[]): RelatedCards;
|
|
17
21
|
}
|
|
@@ -23,6 +27,9 @@ export declare const RELATIONSHIP_OPTIONS: readonly {
|
|
|
23
27
|
}[];
|
|
24
28
|
export declare function relationshipByKey(key: string | null | undefined): Relationship | undefined;
|
|
25
29
|
export declare function relationshipsFor(kind: ProductKind): Relationship[];
|
|
30
|
+
export declare function answersWithProducts(relationship: Relationship): relationship is Relationship & {
|
|
31
|
+
to: ProductKind;
|
|
32
|
+
};
|
|
26
33
|
export declare function relationshipApplies(relationship: Relationship, kind: ProductKind): boolean;
|
|
27
34
|
export declare const CARD_ROWS_NOT_ON_A_TYRE: readonly string[];
|
|
28
35
|
export declare function answersWithTyres(key: string | null | undefined): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CARD_HOVER_KEYS as o,HOVER_GROUP_KEY as r}from"efficient-web-builder/format/lib/animation/hover";const
|
|
1
|
+
import{CARD_HOVER_KEYS as o,HOVER_GROUP_KEY as r}from"efficient-web-builder/format/lib/animation/hover";const n={kind:"tyre",tyres:[]},i={kind:"alloy-wheel",wheels:[]},s={kind:"bundle",bundles:[]},t=[{key:"more-like-this",label:"Similar products",from:["alloy-wheel"],to:"alloy-wheel",heading:"Others you might *like.*",resolve:(e,l)=>({kind:"alloy-wheel",wheels:l})},{key:"tyres-that-fit",label:"Compatible tyres",from:["alloy-wheel"],to:"tyre",heading:"Compatible *tyres.*",resolve:e=>e.kind==="alloy-wheel"?{kind:"tyre",tyres:e.source.compatibleTyres??[]}:n},{key:"wheels-that-fit",label:"Compatible wheels",from:["tyre"],to:"alloy-wheel",heading:"Wheels that *fit.*",resolve:(e,l)=>e.kind==="tyre"?{kind:"alloy-wheel",wheels:l}:i},{key:"bundles",label:"Bundles",from:["alloy-wheel"],to:"bundle",heading:"Buy it *with.*",resolve:e=>e.kind==="alloy-wheel"?{kind:"bundle",bundles:e.source.bundles??[]}:s}],d="more-like-this",u=t.filter(e=>h(e)).map(e=>({value:e.key,label:e.label}));function a(e){return t.find(l=>l.key===e)}function c(e){return t.filter(l=>l.from.includes(e))}function h(e){return e.to!=="bundle"}function k(e,l){return e.from.includes(l)}const b=["coverIndex","imageBackground",r,...Object.values(o),"showBadge"];function p(e){return a(e)?.to==="tyre"}export{b as CARD_ROWS_NOT_ON_A_TYRE,d as DEFAULT_RELATIONSHIP,t as RELATIONSHIPS,u as RELATIONSHIP_OPTIONS,h as answersWithProducts,p as answersWithTyres,k as relationshipApplies,a as relationshipByKey,c as relationshipsFor};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Bundle, Currency } from "./api/index.js";
|
|
1
2
|
export declare const WHEELS_PER_SET = 4;
|
|
2
3
|
export interface SetComponent {
|
|
3
4
|
partNumber: string;
|
|
@@ -41,3 +42,4 @@ export declare const PRICE_LOCALE = "en";
|
|
|
41
42
|
export declare function currencyFormat(currency: string, minimumFractionDigits?: number, maximumFractionDigits?: number): Intl.NumberFormat;
|
|
42
43
|
export declare function formatPrice(amount: number, currency: string, decimalPlaces?: number): string;
|
|
43
44
|
export declare function formatMoneyInCurrency(amount: number, currency: string): string;
|
|
45
|
+
export declare function bundleSaving(bundle: Pick<Bundle, "savings" | "savingIsFrom">, currency: Currency): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const x=4;function E(e,t){return e.map(r=>({partNumber:r.partNumber,quantity:r.wheels*t}))}function _(e,t){if(e.length===0)return null;let r=0;for(const n of e){const s=n.prices?.[t];if(typeof s!="number"||!Number.isFinite(s)||s<=0)return null;r+=s*n.wheels}return r}const u=4,h=1,P={unit:"set",spares:0,spareSide:"left"};function f(e){return e.unit==="single"?1:u+e.spares}function g(e,t){return[{partNumber:e.partNumber,wheels:f(t),prices:e.prices}]}function T(e,t){const r=f(t)-u;if(r<=0||e.length===0)return e;const n=l(e),s=n?n[t.spareSide]:0;return e.map((o,p)=>p===s?{...o,wheels:o.wheels+r}:o)}function l(e){let t,r;for(let n=0;n<e.length;n+=1){const s=e[n].hand;if(s!=="left"&&s!=="right")continue;if((s==="left"?t:r)!==void 0)return null;s==="left"?t=n:r=n}return t!==void 0&&r!==void 0?{left:t,right:r}:null}function y(e){const t=typeof e.spares=="number"?e.spares:e.spare?1:0;return{unit:e.unit,spares:t,spareSide:e.spareSide??"left"}}function c(e,t){return t.spares>0?`${e} + spare`:e}function b(e){return e.unit==="single"?"Single":c(`Set of ${u}`,e)}const A="data-add-to-basket",C=9,d="en",i=new Map;function a(e,t,r){const n=`${e}|${t??""}|${r??""}`;let s=i.get(n);return s||(s=new Intl.NumberFormat(d,{style:"currency",currency:e,...t===void 0?{}:{minimumFractionDigits:t},...r===void 0?{}:{maximumFractionDigits:r}}),i.set(n,s)),s}function S(e,t,r=0){return a(t,0,r).format(e)}function w(e,t){return a(t).format(e)}function L(e,t){const r=e.savings[t];if(r===void 0)return null;const n=S(r,t);return e.savingIsFrom?`Save from ${n}`:`Save ${n}`}export{A as ADD_TO_BASKET_ATTR,P as DEFAULT_PURCHASE_CHOICE,C as MAX_QTY_PER_LINE,h as MAX_SPARES,d as PRICE_LOCALE,u as UNITS_PER_SET,x as WHEELS_PER_SET,L as bundleSaving,a as currencyFormat,w as formatMoneyInCurrency,S as formatPrice,E as orderLinesForSets,g as packComposition,b as packLabel,y as purchaseChoiceFromPack,T as setPackComposition,_ as setPrice,l as spareTargetsByHand,f as unitsPerPack,c as withSpare};
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
import{say as
|
|
2
|
-
|
|
3
|
-
`).replace(/<br\s*\/?>/gi,`
|
|
4
|
-
|
|
5
|
-
`).replace(/<[^>]+>/g,""):r).split(/\n{2,}/).map(e=>n(e).replace(/[ \t]+/g," ").trim()).filter(Boolean):[]}function s(r){return r.length<60&&/^[A-Z][^.]*\.$/.test(r.trim())}function u(r){return typeof r!="string"||!r.trim()?[]:i(o(r)).map(a=>s(a)?{heading:a,paragraph:""}:{heading:"",paragraph:a})}function d(){return[{heading:t("A subhead."),paragraph:""},{heading:"",paragraph:t("Each paragraph of the post's body is drawn by the card template.")},{heading:"",paragraph:t("Another paragraph.")}]}export{l as ARTICLE_BODY_FIELD,g as BLOG_POST_RECORD_TYPE,u as articleRows,d as sampleArticleRows};
|
|
1
|
+
import{htmlToMarkupRows as a}from"efficient-easel/markup-from-html";import{say as n}from"efficient-web-builder/format/lib/editor-words";import{SHOP_MARKUP as i}from"efficient-web-builder/format/lib/markup";import{sanitizeHtmlFragment as h}from"efficient-web-builder/render/lib/document/sanitize";const T="blog-post",R="body",f=t=>({nodeType:3,nodeName:"#text",textContent:t,childNodes:[]}),m=/\n[ \t]*\n\s*/;function p(t){for(const e of Array.from(t.childNodes)){if(e.nodeType!==3){p(e);continue}const o=(e.textContent??"").split(m);if(o.length<2)continue;const r=e.ownerDocument;r&&(o.forEach((c,s)=>{s>0&&t.insertBefore(r.createElement("br"),e),t.insertBefore(r.createTextNode(c),e)}),t.removeChild(e))}}function d(t){const e=h(t);return p(e),e}function u(t){return t.length<60&&/^[A-Z][^.]*\.$/.test(t.trim())}function g(t){return a(f(t.plain),i)[0]?.markup??""}function _(t){return typeof t!="string"||!t.trim()?[]:a(d(t),i).map(e=>u(e.plain)?{heading:g(e),paragraph:""}:{heading:"",paragraph:e.markup})}function b(){return[{heading:n("A subhead."),paragraph:""},{heading:"",paragraph:n("Each paragraph of the post's body is drawn by the card template.")},{heading:"",paragraph:n("Another paragraph.")}]}export{R as ARTICLE_BODY_FIELD,T as BLOG_POST_RECORD_TYPE,_ as articleRows,b as sampleArticleRows};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type SeededNode } from "efficient-web-builder/format/lib/document/seed-parts";
|
|
2
|
+
type Props = Record<string, unknown>;
|
|
3
|
+
export declare const FILTER_OPTIONS_FIELD = "options";
|
|
4
|
+
export declare const FILTER_TEMPLATE_ALLOW: readonly ["Text", "ImageBlock", "Flex", "CardList"];
|
|
5
|
+
export declare const FILTER_CHIPS_TEMPLATE_ALLOW: readonly ["Text", "ImageBlock", "Flex"];
|
|
6
|
+
export declare function filterCardSeed(nodeId: string): SeededNode[];
|
|
7
|
+
export declare function filterChipSeed(nodeId: string): SeededNode[];
|
|
8
|
+
export declare function withFilterTemplate(props: Props): Props;
|
|
9
|
+
export declare function withFilterChipsTemplate(props: Props): Props;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CARD_LIST_TYPE as c,CARD_ROW_FIELD_PROP as f}from"efficient-web-builder/format/lib/content/card-template";import{BOX_TYPE as n,CONTAINER_BLOCKS_SLOT as p}from"efficient-web-builder/format/lib/document/container-blocks";import{rowFieldTextSeed as r}from"efficient-web-builder/format/lib/document/blocks/general/Cards/card-seed";import{BOX as L,DIM as s,INNER_BOX as E,TEXT as l,boxPadding as m,seedNodes as O,token as d}from"efficient-web-builder/format/lib/document/seed-parts";const I="options",R=["Text","ImageBlock",n,c],b=["Text","ImageBlock",n],u=(e,t)=>({textStyle:"body-5",...d("label",e),case:"upper",letterSpacing:t,lineHeight:1.2}),P=u(12,.32),T=u(12,.18),_={textStyle:"body-5",...d("label",11),case:"upper",letterSpacing:.14,lineHeight:1.2,color:"main"},a=(e,t,i={})=>({...L,direction:"row",align:"center",gap:e,gapPhone:e,phoneRow:2,sharePhone:"content",...t?{wrapPhone:"nowrap"}:{},...i}),x=()=>({type:n,props:{...a(8,!0),name:"Option",...m(8,12),sectionBorder:{width:1}},slots:{[p]:[r("label",{...l,tag:"p"},T),r("count",{...s,tag:"p"},T)]}});function S(e){const t=o=>o==="0"?`${e}~group`:`${e}~group.${o.slice(2)}`,i={type:n,props:{...E,name:"Group",gap:12,gapPhone:12},slots:{[p]:[r("label",{...s,tag:"p"},P),{type:n,props:{...a(8,!1,{align:"start",wrap:!0}),name:"Options"},slots:{[p]:[{type:c,props:{[f]:I},slots:{template:[x()]}}]}}]}};return O([i],(o,h)=>t(h))}function w(e){const t={type:n,props:{...a(8,!0),name:"Chip",...m(4,8),sectionBorder:{width:1}},slots:{[p]:[r("label",{...l,tag:"p"},_),r("mark",{...l,tag:"p"},_)]}};return O([t],(i,o)=>o==="0"?`${e}~chip`:`${e}~chip.${o.slice(2)}`)}const g=(e,t)=>typeof e.id=="string"&&e.id.trim()?e.id:t;function A(e){return e.template!==void 0?e:{...e,template:S(g(e,"FilterBlock"))}}function N(e){return e.template!==void 0?e:{...e,template:w(g(e,"FilterChipsBlock"))}}export{b as FILTER_CHIPS_TEMPLATE_ALLOW,I as FILTER_OPTIONS_FIELD,R as FILTER_TEMPLATE_ALLOW,S as filterCardSeed,w as filterChipSeed,N as withFilterChipsTemplate,A as withFilterTemplate};
|
|
@@ -15,6 +15,9 @@ export declare const PRODUCT_CARD_FIELDS: readonly [{
|
|
|
15
15
|
}, {
|
|
16
16
|
readonly key: "eyebrow";
|
|
17
17
|
readonly label: "Eyebrow";
|
|
18
|
+
}, {
|
|
19
|
+
readonly key: "note";
|
|
20
|
+
readonly label: "Note";
|
|
18
21
|
}, {
|
|
19
22
|
readonly key: "href";
|
|
20
23
|
readonly label: "Product page";
|
|
@@ -24,6 +27,8 @@ export interface ProductCardSeedOptions {
|
|
|
24
27
|
legacyWellHonoured?: boolean;
|
|
25
28
|
}
|
|
26
29
|
export declare function productCardSeed(props: Props, options?: ProductCardSeedOptions): BlockSeed;
|
|
30
|
+
export declare function kitCardSeed(props: Props): BlockSeed;
|
|
31
|
+
export declare function withKitCardTemplate(props: Props): Props;
|
|
27
32
|
export declare function productCardTemplate(props: Props, options?: ProductCardSeedOptions): SeededNode[];
|
|
28
33
|
export declare function withProductCardTemplate(props: Props, options?: ProductCardSeedOptions): Props;
|
|
29
34
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BOX_TYPE as
|
|
1
|
+
import{BOX_TYPE as c,CONTAINER_BLOCKS_SLOT as s}from"efficient-web-builder/format/lib/document/container-blocks";import{DIM as D,INNER_BOX as u,boxPadding as C,seedNodes as P,token as x}from"efficient-web-builder/format/lib/document/seed-parts";import{CARD_ROW_FIELD_PROP as E}from"efficient-web-builder/format/lib/content/card-template";import{CARDS_BODY_LOOK as S}from"efficient-web-builder/format/lib/document/blocks/general/Cards/card-seed";import{THEME_CARD_IMAGE_BG as w,resolveBoundCardImageBackground as I}from"efficient-web-builder/format/lib/content/card-image-background";import{SHARED_ROWS_KEY as K}from"efficient-web-builder/render/lib/content/box-shared-columns";import{GRID_CARD_SHOW as _}from"../sections/card-show-defaults.js";const g="ProductPicture",l="ProductSpecs",m="ProductBuy",p="ProductPrice",f="ProductColour",b="ProductSize",B="ProductEyebrow",O="ProductName",Z=[g,B,O,l,p,f,b,m],j=[{key:"name",label:"Name"},{key:"eyebrow",label:"Eyebrow"},{key:"note",label:"Note"},{key:"href",label:"Product page",kind:"link"}],L={...u,gap:0,gapPhone:0,...C(32,32,32,32),[K]:"shared"},h=e=>typeof e.id=="string"&&e.id.trim()?e.id:"ProductGrid",a=(e,t)=>typeof e=="boolean"?e:t,k={type:"Text",props:{...D,tag:"p",text:"",[E]:"note",_partStyles:{text:{...S,...x("body",14),lineHeight:1.375}}}};function A(e,t={}){const n=e.dynamic===!0,o={},i=n?t.legacyWellHonoured?e.imageBackground??w:I(e.imageBackground):e.imageBackground;i!==void 0&&(o.imageBackground=i);for(const d of["cardImage","coverIndex","indexBadge","showBadge"])e[d]!==void 0&&(o[d]=e[d]);const r={price:a(e.showCardPrice,!0),finishes:a(e.showCardFinishes,!0),sizes:a(e.showCardSizes,_.showCardSizes),buy:a(e.showCardBuy,_.showCardBuy),page:a(e.showCardPage,_.showCardPage)},y={...L,name:"Card"};e.outline==="hairline"&&(y.sectionBorder={width:1,style:"solid"});const T=[{type:g,props:o},{type:B},{type:O},{type:l,props:{sizes:r.sizes}},...r.price?[{type:p}]:[],...r.finishes?[{type:f}]:[],...r.buy||r.page?[{type:m,props:{buy:r.buy,page:r.page}}]:[]];return{type:c,props:y,slots:{[s]:T}}}const U={...u,gap:0,gapPhone:0,...C(0,0,0,0)},N={...u,gap:8,gapPhone:8,...C(16,20,16,20)},z={role:"heading",size:18,weight:500,case:"none",letterSpacing:-.015,lineHeight:1.2},R=24;function H(e){const t={frame:"full"};for(const o of["cardImage","showBadge"])e[o]!==void 0&&(t[o]=e[o]);const n={type:c,props:{...N,name:"Copy"},slots:{[s]:[{type:O,props:{fixedHeight:!1,_partStyles:{"@name":z}}},k,{type:p}]}};return{type:c,props:{...U,name:"Card"},slots:{[s]:[{type:g,props:t},n]}}}function q(e){if(e.template!==void 0)return e;const t=h(e);return{...e,gap:e.gap??R,gapPhone:e.gapPhone??R,template:P([H(e)],(n,o)=>`${t}~card-${o}-${n}`)}}function G(e,t={}){const n=h(e);return P([A(e,t)],(o,i)=>`${n}~card-${i}-${o}`)}function J(e,t={}){return e.template!==void 0?e:{...e,template:G(e,t)}}export{m as PRODUCT_BUY_BLOCK,j as PRODUCT_CARD_FIELDS,Z as PRODUCT_CARD_SLOT_BLOCKS,f as PRODUCT_COLOUR_BLOCK,B as PRODUCT_EYEBROW_BLOCK,O as PRODUCT_NAME_BLOCK,g as PRODUCT_PICTURE_BLOCK,p as PRODUCT_PRICE_BLOCK,b as PRODUCT_SIZE_BLOCK,l as PRODUCT_SPECS_BLOCK,H as kitCardSeed,A as productCardSeed,G as productCardTemplate,q as withKitCardTemplate,J as withProductCardTemplate};
|